SQL Server Merging help needed - sql-server

I can't work out how to do this:
Surname Firstname EmpID ListName
--------------------------------
Smith john 123 list1
Smith john 123 list2
Jones James 124 list1
I need
Surname Firstname EmpID ListName1 ListName2
--------------------------------------------
Smith john 123 list1 List 2
Jones James 124 list1 *null*

Just add a number for the rows, with something like this:
select row_number() over (partition by Surname Firstname EmpID order by ListName) as RN, ...
And then use that row number for deciding what data to show where with something like:
select Surname Firstname EmpID,
max(case when RN = 1 then ListName end) as ListName1,
max(case when RN = 2 then ListName end) as ListName2
from (

Related

Group By selecting fixed rows returned and ignoring the top row SQL Server

I have a table:
Customer Purchase
John 5
John 8
John 3
John 1
Sally 3
Sally 5
Sally 2
I want to return two records per customer ignoring the top purchase:
John 5
John 3
Sally 3
Sally 2
With ROW_NUMBER() window function:
select t.customer, t.purchase
from (
select *, row_number() over (partition by customer order by purchase desc) rn
from tablename
) t
where t.rn between 2 and 3

T-SQL - Return records with same values in two columns, but different value in third column

Given this sample data:
ID lname fname num
1 Jones Mary 672
2 Jones Mary 123
3 Johnson Ellen 853
4 Jones Mary 123
5 Jones Scott 342
6 Smith John 874
7 Anders David 433
8 Northson Sue 756
9 Fredricks George 555
10 Northson Sue 756
11 Northson Sue 756
12 Perry Nicole 335
11 Northson Sue 342
I want to find all lname/fname pairs that have multiple "num"s and the count of rows with that "num" value.
So the result set should look like this:
lname fname num count
Jones Mary 672 1
Jones Mary 123 2
Northson Sue 756 3
Northson Sue 342 1
The only thing that I could come up with is the below, but the select in the where clause returns more than row
select
lname
,fname
,num
,COUNT(*)
from sampleTable
where
(num != (select x.num
from sampleTable x
where x.ID != sampleTable.ID
and x.fname = sampleTable.fname
and x.lname = sampleTable.lname)
)
group by lname, fname, num
--having count(num) > 1
order by lname, fname, num
Another approach is to join on another query and count the number of distinct nums per lname/fname combination:
SELECT a.lname, a.fname, a.num, a.cnt
FROM (SELECT lname, fname, num, COUNT(*) AS cnt
FROM sampleatable
GROUP BY lname, fname, num) a
JOIN (SELECT lname, fname
FROM sampletable
GROUP BY lname, fname
HAVING COUNT(DISTINCT num) > 1) b ON a.lname = b.lname AND a.fname = b.fname
select lname, fname, num,
row_number() over(PARTITION BY lname, fname, num ORDER BY lname, fname, num) as cnt,
row_number() over(PARTITION BY lname, fname ORDER BY lname, fname) as pairs
from sampleTable
returns (from my temp version of your table)
lname fname num cnt pairs
Jones Mary 123 1 1
Jones Mary 672 1 2
Jones Scott 111 1 1
Jones Scott 111 2 2
Jones Scott 342 1 3
Jones Scott 874 1 4

PIVOT two columns and keep others as they are

I want to turn some of the rows into columns while keeping other rows as they are.
ID name value RefId
1 Fname John 32145
2 LName Smith 32145
3 Fname Peter 34589
4 LName Mahlang 34589
Now what I want to achieve is to turn the Fname and Lname rows into columns with their matching value field. ID column doesn't really matter, I don't need it.
Desired Output
Fname Lname RefId
John Smith 32145
Peter Mahlang 34589
Any help
Using conditional aggregation:
select
Fname = max(case when name = 'Fname' then value end)
, Lname = max(case when name = 'Lname' then value end)
, RefId
from t
group by RefId
rextester demo: http://rextester.com/MRMY11592
returns:
+---------+---------+-------+
| Fname | Lname | RefId |
+---------+---------+-------+
| John | Smith | 32145 |
| Peter | Mahlang | 34589 |
+---------+---------+-------+
Or using pivot()
select
Fname
, Lname
, RefId
from (select name, value, refid from t) s
pivot(max(value) for name in ([Fname],[Lname]))p

compare data between 2 tables with multiple same records in each table

Heres the situation... i dont have a unique identifier between tables to do matching, so i am matching on a value that can be present more than one time in both tables. I am feeling like i have have to assign some value and then remove the record from being available for matching when the next record tries to match.
Table 1 has the following data:
MedicationName ID Pt Price SEQ
Drug1 123 AAA 100.00 1
Drug2 345 AAA 200.00 2
Table 2
InjectionName ID PT StarDate EndDate
Drug1 123 AAA 20170101 20991231
Drug1 123 AAA 20160417 NULL
Drug2 345 AAA 20161101 20191231
The result should be this:
Medication MedID Price Injection InjID StartDate EndDate PT Seq
Drug1 123 100.00 Drug1 123 20170101 20991231 AAA 1
*NULL NULL NULL Drug1 123 20160417 NULL AAA NULL*
Drug2 345 200.00 Drug2 345 20161101 20191231 AAA 2
But my result is this:
Medication MedID Price Injection InjID StartDate EndDate PT Seq
Drug1 123 100.00 Drug1 123 20170101 20991231 AAA 1
*Drug1 123 100.00 Drug1 123 20160417 NULL AAA 1*
Drug2 345 200.00 Drug2 345 20161101 20191231 AAA 2
I need to show that the 2nd item from the 2nd table does not have a matching value in table 1 because item 1 already matched against it.
You will need ROW_NUMBER to separate rows out.. try this:
With Table1 As
(
Select 'Drug1' MedicationName , 123 ID ,'AAA' Pt ,100.00 Price,1 SEQ
Union Select 'Drug2' MedicationName , 345 ID ,'AAA' Pt ,100.00 Price,1 SEQ
),
Table2 As
(
Select 'Drug1' InjectionName, 123 ID, 'AAA' PT, 20170101 StarDate, 20991231 EndDate
Union Select 'Drug1' InjectionName, 123, 'AAA', 20160417, NULL
Union Select 'Drug2' InjectionName, 345, 'AAA', 20161101, 20191231
),
Table1_Id As
(
Select
Cast (Row_Number() Over (Partition By MedicationName, ID Order BY MedicationName, Id) as Int) MedicationNumber,
MedicationName, Id, PT, Price, Seq
From Table1
),
Table2_Id As
(
Select
Cast (Row_Number() Over (Partition By InjectionName, ID Order BY InjectionName, Id) as Int) InjectionNumber,
InjectionName, Id, PT, StarDate, EndDate
From Table2
)
Select *
From Table1_Id T1
Full Outer Join Table2_Id T2
On T1.MedicationName = T2.InjectionName
And T1.ID = T2.ID
And T1.MedicationNumber = T2.InjectionNumber

Trigger to auto-increment ID based on certain criteria in TSQL

I would like to write a trigger so that when a new record comes in, if certain columns of it contains the same content as the previous record, one particular ID column for all existing entries would increase by 1 and the new entry would be 0, and if there is no existing record, the new record is automatically assigned to have ID 0 in that column.
For example, say my existing data is like this:
FirstName LastName InvoiceID Amt
-----------------------------------
John Doe 1 $5
Bill Jane 0 $6
John Doe 0 $3
Now say I want to insert John Doe with $3.5 of invoice, then the record would automatically becomes:
FirstName LastName InvoiceID Amt
-----------------------------------
John Doe 1 $5
Bill Jane 0 $6
John Doe 2 $3
John Doe 0 $3.5
Now if I need to insert someone new, say Jane Smith for $2, it would become:
FirstName LastName InvoiceID Amt
--------------------------------------
John Doe 1 $5
Bill Jane 0 $6
John Doe 2 $3
John Doe 0 $3.5
Jane Smith 0 $2
May I know how should write such trigger in T-SQL?
Thanks!
Here's what I would do, rather than having the trigger:
create table T (TID int IDENTITY(1,1) not null,FirstName varchar(10) not null,LastName varchar(10) not null,Amt decimal(18,4) not null)
go
create view V
as
select
FirstName,
LastName,
ROW_NUMBER() OVER (PARTITION BY FirstName,LastName ORDER BY TID desc) - 1 as InvoiceID,
Amt
from
T
go
And then set up your initial data:
insert into T(FirstName,LastName,Amt) values
('John','Doe',5),
('Bill','Jane',6)
go
insert into T(FirstName,LastName,Amt) values
('John','Doe',3)
And the new John Doe row:
insert into T(FirstName,LastName,Amt) values
('John','Doe',3.5)
And finally the Jane Smith row:
insert into T(FirstName,LastName,Amt) values
('Jane','Smith',2)
And then select from the view:
FirstName LastName InvoiceID Amt
---------- ---------- -------------------- ---------------------------------------
Bill Jane 0 6.0000
Jane Smith 0 2.0000
John Doe 0 3.5000
John Doe 1 3.0000
John Doe 2 5.0000
And so we have no concern that InvoiceID might be incorrect because we never store it.
select * from V

Resources