Get a column value that showed up more than 3 times in a table - sql

I am trying to filter out and show all the item_number that showed up at least 3 times or more. Below is my SQL query that I am have written.
SELECT row_number() over(partition by i.item_number order by i.item_number) row_num
,i.item_number
,sto.location_id
,sto.actual_qty
,trn.source_location_id
,trn.tran_qty
FROM #items i
LEFT JOIN (select loc.location_wh, sto.item_number, sto.location_id, sto.actual_qty, sto.status from t_stored_item sto WITH (NOLOCK)
INNER JOIN t_location loc WITH (NOLOCK)
on loc.location_id = sto.location_id
where loc.location_wh = '80'
and loc.type = 'I') sto
ON sto.item_number = i.item_number
LEFT JOIN (select t.item_number, t.source_location_id, sum(t.tran_qty) tran_qty from t_tran_log t WITH (NOLOCK)
WHERE t.tran_type = '305'
and convert(date, end_tran_date AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time') = '2021-11-16'
GROUP BY t.item_number, t.source_location_id) trn
on trn.item_number = i.item_number
and trn.source_location_id = sto.location_id
WHERE sto.location_id IS NOT NULL
The data looks like this
row_num item_number location_id actual_qty source_location_id tran_qty
1 1040370 AL-27-03-A 120 NULL NULL
2 1040370 BH-16-04-A 96 NULL NULL
1 1089630 BV-59-04-F 192 NULL NULL
2 1089630 BW-35-05-D 96 NULL NULL
3 1089630 BQ-28-04-A 576 NULL NULL
1 1132345 BZ-32-07-C 804 NULL NULL
2 1132345 AG-51-02-B 588 NULL NULL
3 1132345 BX-28-08-C 60 NULL NULL
4 1132345 AH-18-06-B 600 NULL NULL
5 1132345 BX-14-04-C 108 NULL NULL
Now I want to show all the item_numbers that showed up 3 times at least or more. As you can see, 1089630 showed up 3 times so these should show up in my next nesting query. I tried this but it showed up empty.
;with temp as (
SELECT row_number() over(partition by i.item_number order by i.item_number) row_num
,i.item_number
,sto.location_id
,sto.actual_qty
,trn.source_location_id
,trn.tran_qty
FROM #items i
LEFT JOIN (select loc.location_wh, sto.item_number, sto.location_id, sto.actual_qty, sto.status from t_stored_item sto WITH (NOLOCK)
INNER JOIN t_location loc WITH (NOLOCK)
on loc.location_id = sto.location_id
where loc.location_wh = '80'
and loc.type = 'I') sto
ON sto.item_number = i.item_number
LEFT JOIN (select t.item_number, t.source_location_id, sum(t.tran_qty) tran_qty from t_tran_log t WITH (NOLOCK)
WHERE t.tran_type = '305'
and convert(date, end_tran_date AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time') = '2021-11-16'
GROUP BY t.item_number, t.source_location_id) trn
on trn.item_number = i.item_number
and trn.source_location_id = sto.location_id
WHERE sto.location_id IS NOT NULL
--ORDER BY item_number
)
select row_num, item_number, location_id, actual_qty, source_location_id, tran_qty
from temp
GROUP BY row_num, item_number, location_id, actual_qty, source_location_id, tran_qty
having count(item_number) >= 3
Can anyone please help?

Related

Move two or more columns as starting columns in SQL depending on values

AnimalId
Date
Remark
Number
PA
PCountA
PB
PCountB
PC
PCountC
PD
PCountD
AN001
2022-01-25
LR
22025002
coli
100
Strep ag
100
Strep s
100
Staph a
100
AN001
2022-01-25
12:10am
22025002
coli
300
Staph a
101
Strep s
100
Strep ag
100
AN002
2022-01-25
1:50am
22025002
coli
1500
Staph a
1100
null
null
null
null
AN003
2022-01-25
1:20pm
22025002
Haem
TNTC
Staph a
320
Strep s
TNTC
Strep ag
100
AN004
2022-01-25
1:10pm
22025002
coli
50
Staph s
400
Staph a
100
Strep ag
100
AN004
2022-01-25
1:50pm
22025002
0 growth
null
null
null
null
null
null
null
I have a pivoted view as shown in the above table. It has Pathogens e.g PA found in an animal sample AnimalId and the pathogen counts e.g PCountA. There are pathogens Staph a and Strep ag that when found, the pathogen and its result should come first/listed in the first column. For example,in the second row AN001, Staph a under column PB and it's count under column PCountB should shift to columns PA and PCountA, i.e it should be the starting pathogen.
In cases where we have both pathogens Staph a and Strep aglike in the first row, Staph a should start followed by Strep ag then the rest.
How do I achieve this in SQL Server?
Note: I tried CASE ordering by Pathogen before pivoting but it didn't work out.
See below.
SELECT AnimalId, Date, Remark, Number,
PA, PCountA, PB, PRCountB, PC, PCountC,
PD, PCountD
FROM (
SELECT AnimalId, Date, Remark, Number, Col, Val
FROM (
SELECT AnimalId, Date, Remark, Number, Pathogen,
PathogenResult,
CASE
WHEN PathogensCount = 1 THEN 'PA'
WHEN PathogensCount = 2 THEN 'PB'
WHEN PathogensCount = 3 THEN 'PC'
WHEN PathogensCount = 4 THEN 'PD'
END AS PathogenType
,
CASE
WHEN PathogensCount = 1 THEN 'PCountA'
WHEN PathogensCount = 2 THEN 'PCountB'
WHEN PathogensCount = 3 THEN 'PCountC'
WHEN PathogensCount = 4 THEN 'PCountD'
END AS PathogenResultType
FROM (
SELECT * FROM (
SELECT * FROM (
SELECT s.AnimalId, s.SampleDate AS Date, s.SampleRemark AS Remark, o.Name AS Pathogen,
CASE WHEN o.RequiresCount = 0 THEN NULL
WHEN sr.NewCount = 999999 THEN 'TNTC'
WHEN t.Name LIKE '%tank%' THEN CAST(sr.NewCount * 10 AS nvarchar)
ELSE CAST(sr.NewCount * 100 AS nvarchar)
END AS PathogenResult,
a.Number,
COUNT(
CASE WHEN o.RequiresCount = 0 THEN NULL
WHEN sr.NewCount = 999999 THEN 'TNTC'
WHEN t.Name LIKE '%tank%' THEN CAST(sr.NewCount * 10 AS nvarchar)
ELSE CAST(sr.NewCount * 100 AS nvarchar)
END) OVER(PARTITION BY s.AnimalId) AS CountOfPathogenResult
FROM Table_s s
INNER JOIN Table_sr sr ON sr.ATSId = s.Id
LEFT JOIN Table_o o ON o.Id = sr.NOId
INNER JOIN Table_sp sp ON sp.Id = sr.ATSPId
INNER JOIN Table_a a ON a.Id = sp.AId
INNER JOIN Table_ag ag ON ag.Id = sr.AgId
INNER JOIN Table_ats ats ON ats.AId = a.Id AND ats.Id = sp.ATId
INNER JOIN Table_t t ON t.Id = ats.TId
WHERE o.Name IS NOT NULL
GROUP BY a.Id, s.AnimalId, s.Date, s. SampleRemark, o.Name,
o.RequiresCount, t.Name, sr.NewCount, a.Number, ag.Name
) as A
WHERE CountOfPathogenResult > 0 AND Pathogen <> 'No Growth'
UNION
SELECT * FROM (
SELECT s.AnimalId, s.SampleDate AS Date, s.SampleRemark AS Remark,
o.Name AS Pathogen,
CASE WHEN o.RequiresCount = 0 THEN NULL
WHEN sr.NewCount = 999999 THEN 'TNTC'
WHEN t.Name LIKE '%tank%' THEN CAST(sr.NewCount * 10 AS nvarchar)
ELSE CAST(sr.NewCount * 100 AS nvarchar)
END AS PathogenResult,
a.Number,
COUNT(
CASE WHEN o.RequiresCount = 0 THEN NULL
WHEN sr.NewCount = 999999 THEN 'TNTC'
WHEN t.Name LIKE '%tank%' THEN CAST(sr.NewCount * 10 AS nvarchar)
ELSE CAST(sr.NewCount * 100 AS nvarchar)
END) OVER(PARTITION BY s.AnimalId) AS CountOfPathogenResult
FROM Table_s s
INNER JOIN Table_sr sr ON sr.ATSId = s.Id
LEFT JOIN Table_o o ON o.Id = sr.NOId
INNER JOIN Table_sp sp ON sp.Id = sr.ATSPId
INNER JOIN Table_a a ON a.Id = sp.AId
INNER JOIN Table_ag ag ON ag.Id = sr.AgId
INNER JOIN Table_ats ats ON ats.AId = a.Id AND ats.Id = sp.ATId
INNER JOIN Table_t t ON t.Id = ats.TId
WHERE o.Name IS NOT NULL
GROUP BY a.Id, s.AnimalId, s.Date, s. SampleRemark, o.Name,
o.RequiresCount, t.Name, sr.NewCount, a.Number, ag.Name
) as B
WHERE CountOfPathogenResult = 0 AND Pathogen = 'No Growth' OR CountOfPathogenResult = 0 AND Pathogen = 'Contaminated'
) AS C
ORDER BY CASE WHEN Pathogen = 'Staph aureus' THEN 1
WHEN Pathogen = 'Strep. ag.' THEN 2 ELSE 3
END, Pathogen
OFFSET 0 ROWS
) AS ResultsA
GROUP BY AnimalId, Date, Remark,Number, PathogenResult, Pathogen, PathogensCount) AS source cross apply (
SELECT PathogenType, Pathogen
UNION ALL
SELECT PathogenResultType, CAST(PathogenResult AS varchar(45))
) ResultsB (Col, Val)
) ResultsC
PIVOT (MAX(Val) FOR Col IN (
[PA],
[PCountA],
[PB],
[PaCountB],
[PC],
[PaCountC],
[PD],
[PaCountD],
[PathogenE])
) AS PivotResults;
GO
Expected Results
AnimalId
Date
Remark
Number
PA
PCountA
PB
PCountB
PC
PCountC
PD
PCountD
AN001
2022-01-25
LR
22025002
Staph a
100
Strep ag
100
coli
100
Strep s
100
AN001
2022-01-25
12:10am
22025002
Staph a
101
Strep ag
100
coli
300
Strep s
100
AN002
2022-01-25
1:50am
22025002
Staph a
1100
coli
1500
null
null
null
null
AN003
2022-01-25
1:20pm
22025002
Staph a
320
Strep ag
100
Haem
TNTC
Strep s
TNTC
AN004
2022-01-25
1:10pm
22025002
Staph a
100
Strep ag
100
coli
50
Staph s
400
AN004
2022-01-25
1:50pm
22025002
No growth
null
null
null
null
null
null
null
I see you are aleady using the idea I had when reading the problem:
ORDER BY CASE WHEN Pathogen = 'Staph aureus' THEN 1
WHEN Pathogen = 'Strep. ag.' THEN 2 ELSE 3
but according to the output the actual names found in the data are Strep ag, Strep s and Staph a so everything is being sorted with a value of 3.
You could use the following, which would allow some tolerance for future differences.
ORDER BY CASE LEFT(Pathogen,5) WHEN 'Staph' THEN 1
WHEN Pathogen = 'Strep' THEN 2 ELSE 3
or if you want to rest exact use the following
ORDER BY CASE
WHEN Pathogen = 'Staph a' THEN 1
WHEN Pathogen = 'Strep ag' THEN 2
WHEN Pathogen = 'Strep s' THEN 2
ELSE 3

How to return 1 row instead of 3 when one column has different data

I have 3 rows of data returned from a query
OrderId | OtherId
--------+---------
1234 | 444
1234 | 555
1234 | 666
How to return data in this format
OrderId | OtherId | OtherId2 | OtherId
--------+---------+----------+--------
1234 | 444 | 555 | 666
Can I use Distinct for this problem?
EDIT
The result set comes from a query such as
left join (
Select distinct
o.id
,OL2.db
,case
when i.cust = 'cust2' then
case
when
lower(pdf.dept) not like 'abc%' or pdf.dept is null
then 'Yes'
else'No'
end
else 'Yes'
end as 'Show'
,otherId
from order o with(nolock)
Join instance i with(nolock) on i.id = o.id
Join orderLine ol with(nolock) on ol.id = o.SocialNetworker_Order_InstanceId
and ol.id = o.id
join product p with(nolock) on o.id = p.id
and ol.id = p.id
left join productEx pdf with(nolock) on p.id = pdf.id
and o.id = pdf.id
Where i.cust in ('cust1')
) ol2 on OL2.id = sno.id
and OL2.id2 = sno.id2
and i.db = cc.db
How to work solution into the above code?
You can use row_number() and conditional aggregation:
select orderid,
max(case when seqnum = 1 then otherid end) as otherid_1,
max(case when seqnum = 2 then otherid end) as otherid_2,
max(case when seqnum = 3 then otherid end) as otherid_3
from (select t.*, row_number() over (partition by orderid order by otherid) as seqnum
from t
) t
group by orderid;
Use an outer join with cascading join conditions:
select t1.OrderId, t1.OtherId OtherId1, t2.OtherId OtherId2, t3.OtherId OtherId3
from orders t1
left join orders t2 on t2.OrderId = t1.OrderId
and t2.OtherId > t1.OtherId
left join orders t3 on t3.OrderId = t2.OrderId
and t3.OtherId > t2.OtherId
If there are less than 3 other ids, the right-most columns will be null.
This query will work on pretty much any database.

SQL query for converting column values in row dynamically

I am new to SQL so don't know much if you can help me out for eliminating duplicates from my query 1 or help me to transpose query 2
Old query 1: I already tried below query but some duplicate values were returned:
select
ROW_NUMBER() OVER (ORDER BY count(case when TransactionType = 1 then 1 else null end) desc) AS 'td','',
Warehouse as 'td','',
Createdate as 'td','',
count(case when TransactionType = 1 then 1 else null end) as 'td','',
count(case when TransactionType = 5 then 1 else null end) as 'td','',
count(case when TransactionType = 6 then 1 else null end) as 'td','',
cast(round(sum(localamount),8) as decimal(18,2))as 'td',''
from
PaymentTrn (nolock)
where
CreateDate = cast(convert(varchar(8),getdate() -1,112) as int)
group by
Warehouse, CreateDate
order by
count(case when TransactionType = 1 then 1 else null end) desc
Then I tried count(distinct case when TransactionType = 1 then 1 else null end) but is giving only 1.
For query 2 (shown here next), have 3 (useful) columns in DB invoice-type, transaction-type and warehouse from which I need to fetch data.
IMPORTANT: invoice number has duplicates so I need to use distinct
because I am getting duplicate values I modify the query, now I need to convert "no column name " column to row
Current output for a query is:
warehouse no column name
1700 3
1700 6
1700 9
query 2:
select warehouse,count(distinct(invoicenumber))
from PaymentTrn (nolock)
where CreateDate = cast(convert(varchar(8),getdate() -305,112) as int) and TransactionType = 1
group by Warehouse,CreateDate
union all
select warehouse,count(distinct(invoicenumber))
from PaymentTrn (nolock)
where CreateDate = cast(convert(varchar(8),getdate() -305,112) as int) and TransactionType = 5
group by Warehouse,CreateDate
union all
select warehouse,count(distinct(invoicenumber))
from PaymentTrn (nolock)
where CreateDate = cast(convert(varchar(8),getdate() -305,112) as int) and TransactionType = 6
group by Warehouse,CreateDate
the expected result should need to be:
warehouse transactiontype=1 transactiontype=5 transactiontype=6
1700 3 6 9
I think you simply want conditional aggregation with count(distinct). You seem to want to count invoice numbers:
select row_number() over (order by count(distinct case when TransactionType = 1 then invoicenumber end) desc) AS td, '',
Warehouse as td, '',
Createdate as td, '',
count(distinct case when TransactionType = 1 then invoicenumber end) as td, '',
count(distinct case when TransactionType = 5 then invoicenumber end) as td, '',
count(distinct case when TransactionType = 6 then invoicenumber end) as td, '',
cast(round(sum(localamount), 8) as decimal(18,2)) as td, ''
from PaymentTrn
where CreateDate = cast(convert(varchar(8),getdate() -1, 112) as int)
group by Warehouse, CreateDate
order by 1;
Here's your queries.
Query 1:
select t2.rownum as 'td',''
, t1.Warehouse as 'td',''
, t1.Createdate as 'td',''
, t2.cnt as 'td',''
, t3.cnt as 'td',''
, t4.cnt as 'td',''
, cast(round(sum(t1.localamount),8) as decimal(18,2))as 'td',''
from
PaymentTrn t1
left join
(select ROW_NUMBER() OVER (ORDER BY count(1) desc) as rownum, Warehouse
from
PaymentTrn (nolock)
where TransactionType = 1 and CreateDate = cast(convert(varchar(8),getdate() -1,112) as int)
group by Warehouse) t2 on t2.Warehouse = t1.Warehouse
left join
(select count(1) as cnt, Warehouse
from
PaymentTrn (nolock)
where TransactionType = 5 and CreateDate = cast(convert(varchar(8),getdate() -1,112) as int)
group by Warehouse) t3 on t3.Warehouse = t1.Warehouse
left join
(select count(1) as cnt, Warehouse
from
PaymentTrn (nolock)
where TransactionType = 6 and CreateDate = cast(convert(varchar(8),getdate() -1,112) as int)
group by Warehouse) t4 on t4.Warehouse = t1.Warehouse
where
t1.CreateDate = cast(convert(varchar(8),getdate() -1,112) as int)
order by t2.rownum desc
Query 2:
select t1.warehouse, count(distinct(t1.invoicenumber)) as TType1, t2.cnt as TType2, t3.cnt as TType3
from PaymentTrn t1
left join
(select Warehouse, count(distinct(invoicenumber)) as cnt from PaymentTrn
where CreateDate = cast(convert(varchar(8),getdate() -305,112) as int) and TransactionType = 1 group by customer_code) t2
on t2.Warehouse = t1.Warehouse
left join
(select Warehouse, count(distinct(invoicenumber)) as cnt from PaymentTrn
where CreateDate = cast(convert(varchar(8),getdate() -305,112) as int) and TransactionType = 1 group by customer_code) t3
on t3.Warehouse = t1.Warehouse
where t1.CreateDate = cast(convert(varchar(8),getdate() -305,112) as int) and t1.TransactionType = 1
group by t1.Warehouse, t2.TType2, t3.TType3

T-SQL Case when with Using with Sql Two Column

First of all I would like to thank the friends who helped this complex and difficult query.
I have three tables
Table 1
StaffId FirstName LastName staffType
---------------------------------------
1 Adam Sorme Student
2 Lara Sandra Teacher
3 Jack Jones Student
Table 2
GateId GateName
---------------------------------------
1 frontDoor
2 superDoor
Table 3
Id transitionDate GateId StaffId
---------------------------------------
1 2018-01-1 08:00:00 1 1
2 2018-01-1 10:00:00 2 1
3 2018-01-1 20:00:00 2 1
4 2018-01-2 07:00:00 1 2
5 2018-01-2 10:00:00 1 3
6 2018-01-9 12:00:00 2 2
I want the first and last movements of students for each day. Value must be set to null if no movement is available between the specified dates
transitionDate> '2018-01-1 00:00:00 000'
and transitionDate< '2018-01-03 00:00:00 000'
OUTPUT:
Id Date MinTransitionDate MaxTransitionDate FirstGateName LastGateName StaffId StaffType
1 2018-01-01 2018-01-1 08:00:00 2018-01-1 20:00:00 frontDoor superDoor 1 Student
2 2018-01-01 null null null null 3 student
3 2018-01-02 null null null null 1 student
4 2018-01-02 2018-01-2 10:00:00 null frontDoor null 3 student
The following query is partially working.
select
q.*,
g1.GateName as first_gate_name,
g2.GateName as last_gate_name
from
(
select s.staffId, d.dte,
min(t.transitionDate) as min_Date,
max_Date= case when count(1)>1 then max(t.transitionDate) else null end,
max(case when seqnum_asc = 1 then gateId end) as first_gateid,
max(case when seqnum_desc = 1 then gateId end) as last_gateid
from (select s.* from Staff s where stafftype = 'Student') s cross join
(select distinct cast(transitionDate as date) as dte from Transitions) d left join
(select t.*,
row_number() over (partition by StaffId, cast(transitionDate as date) order by transitionDate) as seqnum_asc,
row_number() over (partition by StaffId, cast(transitionDate as date) order by transitionDate desc) as seqnum_desc
from Transitions t
) t
on cast(t.transitiondate as date) = d.dte and
t.staffId = s.staffId and
1 in (t.seqnum_asc, t.seqnum_desc)
group by s.staffId, d.dte
) q
left join Gates g1 on g1.gateId = q.first_gateid
left join Gates g2 on g2.gateId = q.last_gateid
see working demo
Problem : max_date in 4. row is empty. I want the value of last_gateid to be null. Can you help me?
screenshot 4. row
https://cdn.pbrd.co/images/H7vyu31.png
A quick fix would be replacing this line
max(case when seqnum_desc = 1 then gateId end) as last_gateid
with
max(case when (seqnum_desc = 1 and seqnum_asc != 1) then t.gateId end) as last_gateid
It is obvious that some one helped you write the query and you gave him more explanation of the problem , what i did is tweaking the query you provided and used the same logic to give you the desired output although i would prefer to rewrite it in a more understandable way :
select
q.*,
g1.GateName as first_gate_name,
g2.GateName as last_gate_name
from
(
select s.staffId, d.dte,
min(t.transitionDate) as min_Date,
max_Date= case when count(1)>1 then max(t.transitionDate) else null end,
max(case when seqnum_asc = 1 then gateId end) as first_gateid,
case when count(1)>1 then MAX(gateId) end as last_gateid
from (select s.* from Staff s where stafftype = 'Student') s cross join
(select distinct cast(transitionDate as date) as dte from Transitions) d left join
(select t.*,
row_number() over (partition by StaffId, cast(transitionDate as date) order by transitionDate) as seqnum_asc,
row_number() over (partition by StaffId, cast(transitionDate as date) order by transitionDate desc) as seqnum_desc
from Transitions t
) t
on cast(t.transitiondate as date) = d.dte and
t.staffId = s.staffId and
1 in (t.seqnum_asc, t.seqnum_desc)
group by s.staffId, d.dte
) q
left join Gates g1 on g1.gateId = q.first_gateid
left join Gates g2 on g2.gateId = q.last_gateid
IF OBJECT_ID('dbo.Staff') IS NOT NULL DROP TABLE Staff
create table Staff (StaffId int, FirstName varchar(20), LastName
varchar(20), staffType varchar(20))
insert into Staff values
(1, 'Adam', 'Sorme', 'Student'),
(2, 'Lara', 'Sandra', 'Teacher'),
(3, 'Jack', 'Jones', 'Student')
IF OBJECT_ID('dbo.Gates') IS NOT NULL DROP TABLE Gates
create table Gates (GateId int, GateName varchar(20))
insert into Gates values
(1, 'frontDoor'),
(2, 'backDoor')
IF OBJECT_ID('dbo.Transitions') IS NOT NULL DROP TABLE Transitions
create table Transitions (Id int, transitionDate datetime, GateId int,
StaffId int)
insert into Transitions values
(1, '2018-01-1 08:00:00', 1, 1),
(2, '2018-01-1 10:00:00', 2, 1),
(3, '2018-01-1 20:00:00', 2, 1),
(4, '2018-01-2 07:00:00', 1, 2),
(5, '2018-01-2 10:00:00', 2, 3),
(6, '2018-01-9 12:00:00', 2, 2)
--select * from Transitions
DECLARE #Datefrom DATETIME = '2018-01-01'
DECLARE #DateTo DATETIME = '2018-01-03'
----1. If the transition table itself is not reliable meaning there
--could be imports and the maxID could be for a lesser datetime
IF OBJECT_ID('tempdb..#Transitions') IS NOT NULL DROP TABLE
#Transitions
SELECT *, [GateSortID] = RANK() OVER (PARTITION BY StaffID ORDER BY
StaffID,GateID,TransitionDate)
INTO #Transitions
FROM Transitions
----2.Based on above temp table get first and last dates
IF OBJECT_ID('tempdb..#FirstandLastDates') IS NOT NULL DROP TABLE
#FirstandLastDates
SELECT T.StaffId,
[FirstDate] = FirstDate.transitionDate,
[LastDate] = LastDate.transitionDate
INTO #FirstandLastDates
FROM #Transitions T
JOIN
(
SELECT TT.StaffId,
[MinGateSortID] = MIN(GateSortID),
TT.GateID,
G.transitionDate
FROM #Transitions TT
JOIN Transitions G
ON TT.StaffId = G.StaffId
AND TT.Id = G.ID
AND TT.GateId = G.GateId
WHERE GateSortID = 1-- MIN VALUE WILL ALWAYS BE 1
GROUP BY TT.StaffID,TT.GateID,G.transitionDate
)FirstDate --lol!!
ON T.StaffID= FirstDate.StaffID
LEFT JOIN
(
SELECT TT.StaffId, TT.GateId, G.TransitionDate
FROM #Transitions TT
JOIN #Transitions G
ON TT.StaffId = G.StaffId
AND TT.Id = G.ID
AND TT.GateId = G.GateId
JOIN
(
SELECT StaffID,
[MaxGateSortID] = MAX(GateSortID)
FROM #Transitions TT
WHERE GateSortID <> 1 -- SO THAT IF THE PERSON HAS NOT --CLOCKED OUT YET ONLY CLOCKED IN DO NOT CONSIDER THAT THE
--GATES ARE SAME
GROUP BY StaffID
) LastGate1
ON TT.StaffId = LastGate1.StaffId
AND TT.GateSortID = LastGate1.MaxGateSortID
)LastDate
ON T.StaffId = LastDate.StaffId
GROUP BY T.StaffId,FirstDate.transitionDate,LastDate.transitionDate
----3.Based on above temp table get first and last transition gates
IF OBJECT_ID('tempdb..#FirstandLastGates') IS NOT NULL DROP TABLE
#FirstandLastGates
SELECT T.StaffId,
[FirstGate] = FirstGate.GateName,
[LastGate] = LastGate.GateName
INTO #FirstandLastGates
FROM #Transitions T
JOIN
(
SELECT StaffID,
[MinGateSortID] = MIN(GateSortID),
TT.GateID,
GateName
FROM #Transitions TT
JOIN Gates G
ON TT.GateId = G.GateId
WHERE GateSortID = 1-- MIN VALUE WILL ALWAYS BE 1
--AND TT.transitionDate BETWEEN #Datefrom AND #DateTo
GROUP BY StaffID,TT.GateID,GateName
)FirstGate
ON T.StaffID= FirstGate.StaffID
LEFT JOIN
(
SELECT TT.StaffId, TT.GateId, G.GateName
FROM #Transitions TT
JOIN Gates G
ON TT.GateId = G.GateId
JOIN
(
SELECT StaffID,
[MaxGateSortID] = MAX(GateSortID)
FROM #Transitions TT
WHERE GateSortID <> 1 -- SO THAT IF THE PERSON HAS NOT CLOCKED
-- OUT YET ONLY CLOCKED IN DO NOT CONSIDER THAT THE GATES ARE --SAME
--AND TT.transitionDate BETWEEN #Datefrom AND #DateTo
GROUP BY StaffID
) LastGate1
ON TT.StaffId = LastGate1.StaffId
AND TT.GateSortID = LastGate1.MaxGateSortID
)LastGate
ON T.StaffId = LastGate.StaffId
GROUP BY T.StaffId,FirstGate.GateName,LastGate.GateName
--MAIN OUTPUT
SELECT DISTINCT --t.Id,
--t.transitionDate,
[MinTransitionDate] = D.FirstDate,
[MaxTransitionDate] = D.LastDate,
[FirstGateName] = G.FirstGate,
[LastGateName] = G.LastGate,
T.[StaffId],
S.StaffType
from Staff S
JOIN #Transitions T
ON S.StaffId = T.StaffId
JOIN #FirstandLastDates D
ON T.StaffId = D.StaffId
JOIN #FirstandLastGates G
ON T.StaffId = G.StaffId
GROUP BY t.Id, D.FirstDate, D.LastDate, G.FirstGate,G.LastGate,T.[StaffId],
S.StaffType

How to merge two particular rows into single row and reaming rows are same using stored procedure SQL Server 2012

I have data like this. first row of Id 1 from particular time period and second row of id 1 is another time period. so now want to combined id and name which are same in the two time periods reaming are same.if there is no orders from that time period its should be display 0 or null.
Id Name Qty Price
----------------------
1 Rose 4 540
1 Rose 1 640
2 Lilly 5 550
2 Lilly 18 360
3 Grand 2 460
3 Grand 10 360
4 lotus 0 0
4 Lotus 9 580
now I want data like this..
Id Name Qty Price
4 540
1 rose
1 640
5 550
2 Lilly
18 360
2 460
3 Grand
10 360
0 0
4 Lotus
9 580
This is my procedure
create PROCEDURE [dbo].[Sp_Orders]
(
#Startdate varchar(30),
#Enddate varchar(30),
#Startdate1 varchar(30),
#Enddate1 varchar(30)
)
--[Sp_Orders] '03/01/2016','03/15/2016','02/01/2016','02/28/2016'
AS
BEGIN
---First Duration----
SELECT DISTINCT
op.ProductId as id, op.Price as Prc,
sc.SubCategoryName as ScName,
COUNT(op.ProductId) AS Qty,
ROUND(SUM(op.Price * op.Quantity), 0) AS Revenue,
FROM
orderdetails od
INNER JOIN
(SELECT DISTINCT
Orderid, Productid, ProductFeatures, Price, Quantity
FROM
OrderProducts) op ON od.Orderid = op.Orderid
INNER JOIN
products p ON p.productid = op.productid
INNER JOIN
subcategory sc ON sc.subcategoryid = p.subcategoryid
WHERE
CONVERT(datetime, CONVERT(varchar(50), od.DeliveryDate, 101)) BETWEEN #Startdate AND #Enddate
GROUP BY
op.ProductID, op.Price, sc.SubCategoryName
---Second Duration----
SELECT DISTINCT
op.ProductID AS id, op.Price AS Prc,
sc.SubCategoryName AS ScName,
COUNT(op.ProductId) AS Qty,
ROUND(SUM(op.Price * op.Quantity), 0) AS Revenue,
FROM
orderdetails od
INNER JOIN
(SELECT DISTINCT
Orderid, Productid, ProductFeatures, Price, Quantity
FROM
OrderProducts) op ON od.Orderid = op.Orderid
INNER JOIN
products p ON p.productid = op.productid
INNER JOIN
subcategory sc ON sc.subcategoryid = p.subcategoryid
WHERE
CONVERT(datetime, CONVERT(varchar(50),od.DeliveryDate,101)) BETWEEN #Startdate1 AND #Enddate1
GROUP BY
op.ProductID, op.Price, sc.SubCategoryName
END
From what I understood from your Question and Comments:
Schema for your case
SELECT * INTO #TAB FROM(
SELECT 1 ID, 'ROSE' NAME, 4 QTY, 540 PRICE
UNION ALL
SELECT 1 , 'ROSE' , 1 , 640
UNION ALL
SELECT 2 , 'LILLY' , 5 , 550
UNION ALL
SELECT 2 , 'LILLY' , 18 ,360
UNION ALL
SELECT 3 , 'GRAND' , 2 , 460
UNION ALL
SELECT 3 , 'GRAND' , 10 ,360
UNION ALL
SELECT 4 , NULL,NULL,NULL
UNION ALL
SELECT 4 , 'LOTUS' , 9 , 580
) AS A
And the Logic to display is as below
SELECT CASE WHEN SNO=1 THEN CAST(ID AS VARCHAR(250)) ELSE '' END ID,
CASE WHEN SNO=1 THEN ISNULL(NAME,'') ELSE '' END NAME,ISNULL(Qty,0)Qty
,ISNuLL(Price,0)Price FROM (
SELECT ROW_NUMBER() Over(partition by Name, Id ORDER BY (SELECT 1)) SNO
,ID, NAME , Qty, Price, ID AS ID2 FROM #TAB
)AS A
ORDER BY ID2, NAME DESC
Try this from your Procedure. And may need to do type cast based on your actual datatypes
CREATE PROCEDURE [DBO].[SP_ORDERS]
(
#STARTDATE VARCHAR(30),
#ENDDATE VARCHAR(30),
#STARTDATE1 VARCHAR(30),
#ENDDATE1 VARCHAR(30)
)
--[SP_ORDERS] '03/01/2016','03/15/2016','02/01/2016','02/28/2016'
AS
BEGIN
SELECT CASE WHEN SNO=1 THEN CAST(ID AS VARCHAR(250)) ELSE '' END ID,CASE WHEN SNO=1 THEN ISNULL(SCNAME,'') ELSE '' END NAME,ISNULL(QTY,0)QTY,ISNULL(REVENUE,0)PRICE FROM (
SELECT ROW_NUMBER() OVER(PARTITION BY SCNAME, ID ORDER BY (SELECT 1)) SNO, ID, SCNAME , QTY, REVENUE, ID AS ID2 FROM (
SELECT DISTINCT OP.PRODUCTID AS ID,OP.PRICE AS PRC,SC.SUBCATEGORYNAME AS SCNAME,COUNT(OP.PRODUCTID) AS QTY, ROUND(SUM(OP.PRICE * OP.QUANTITY), 0) AS REVENUE
FROM ORDERDETAILS OD INNER JOIN
(SELECT DISTINCT ORDERID,PRODUCTID,PRODUCTFEATURES,PRICE,QUANTITY FROM ORDERPRODUCTS ) OP ON OD.ORDERID=OP.ORDERID
INNER JOIN PRODUCTS P ON P.PRODUCTID=OP.PRODUCTID
INNER JOIN SUBCATEGORY SC ON SC.SUBCATEGORYID=P.SUBCATEGORYID
WHERE CONVERT(DATETIME,CONVERT(VARCHAR(50),OD.DELIVERYDATE,101)) BETWEEN #STARTDATE AND #ENDDATE
GROUP BY OP.PRODUCTID,OP.PRICE,SC.SUBCATEGORYNAME
---SECOND DURATION----
UNION ALL --ADDED NOW
SELECT DISTINCT OP.PRODUCTID AS ID,OP.PRICE AS PRC,SC.SUBCATEGORYNAME AS SCNAME,COUNT(OP.PRODUCTID) AS QTY, ROUND(SUM(OP.PRICE * OP.QUANTITY), 0) AS REVENUE
FROM ORDERDETAILS OD INNER JOIN
(SELECT DISTINCT ORDERID,PRODUCTID,PRODUCTFEATURES,PRICE,QUANTITY FROM ORDERPRODUCTS ) OP ON OD.ORDERID=OP.ORDERID
INNER JOIN PRODUCTS P ON P.PRODUCTID=OP.PRODUCTID
INNER JOIN SUBCATEGORY SC ON SC.SUBCATEGORYID=P.SUBCATEGORYID
WHERE CONVERT(DATETIME,CONVERT(VARCHAR(50),OD.DELIVERYDATE,101)) BETWEEN #STARTDATE1 AND #ENDDATE1
GROUP BY OP.PRODUCTID,OP.PRICE,SC.SUBCATEGORYNAME
)
AS A
)B
ORDER BY ID2, NAME
END
Based on your sample data i have given this Out put but if the data is inconsistent it may not give accurate results if you see the Expected Output it gives exact same
Declare #Table1 TABLE
(Id VARCHAR(10), Name varchar(5),Qty VARCHAR(10), Price varchar(10))
;
INSERT INTO #Table1
(Id, Name,Qty, Price)
VALUES
(1, 'Rose',4, 540),
(1, 'Rose',1, 640),
(2, 'Lilly',5, 550),
(2, 'Lilly',18, 360),
(3, 'Grand',2, 460),
(3, 'Grand',10, 360),
(4,'Lotus',0,0),
(4, 'Lotus',9, 580)
;
SCRIPT
;WITH CTE AS (
Select
CASE WHEN RN = 1 THEN ID ELSE NULL END ID,
CASE WHEN RN = 1 THEN Name ELSE NULL END NAME,
Qty,
Price
from (
select
Id,
Name,
Qty,
Price,
ROW_NUMBER()OVER(PARTITION BY ID,NAME ORDER BY NAME)RN
FROM
#Table1)T)
Select CASE WHEN RN = 2 THEN T.Id ELSE '' END ID,
CASE WHEN RN = 2 THEN T.Name ELSE '' END Name,
CASE WHEN RN IN (1,3) THEN ISNULL(T.Qty,0) ELSE '' END qty,
CASE WHEN RN IN (1,3) THEN ISNULL(T.Price,0) ELSE '' END qty from (
Select
T.ID,
T.NAME,
c.Qty,
C.Price,
ROW_NUMBER()OVER(PARTITION BY T.ID,T.NAME ORDER BY T.NAME)RN
from #Table1 T
INNER JOIN CTE C
ON T.Id = C.ID
AND T.Name = C.NAME
OR (T.Qty = C.Qty OR T.Price = C.Price ))T
WHERE T.RN <> 4