selecting all values in GroupBy - sql

I have a scenario wherein i have three columns in my table. ID(String),Desc (string) TerminationDate, Last Update Date(Time).
There is no primary key, so there might be multiple rows with same set of data but LastUpdate Date will always be different.
I need to write a SP wherein i need to get the latest modified result(ID,Desc, termination date). pls see the example below
ID Desc TerminationDate LastUpdtDt
A test 01-01-2013 01-01-2013
A test1 01-03-2013 25-01-2013
A test 01-01-2013 26-03-2013
B test 01-01-2011 01-01-2013
The result i shuld get is
A test 01-01-2013 26-03-2013
B test 01-01-2011 01-01-2013
Let me know in case you need more information.

SELECT ID, [DESC], TerminationDate, LastUpdtDt
FROM
(
SELECT ID, [DESC], TerminationDate, LastUpdtDt,
ROW_NUMBER() OVER(PARTITION BY ID
ORDER BY LastUpdtDt DESC) rn
FROM TableName
) ss
WHERE rn = 1
SQLFiddle Demo

You could return the rows with the max(LastUpdtDt) using a subquery:
select t1.id,
t1.[desc],
t1.terminationdate,
t1.LastUpdtDt
from yt t1
inner join
(
select max(LastUpdtDt) LastUpdtDt, id
from yt
group by id
) t2
on t1.id = t2.id
and t1.LastUpdtDt = t2.LastUpdtDt;
See SQL Fiddle with Demo.

SELECT ID ,
DESC ,
TERMINATION_DATE ,
LAST_UPDATE
FROM ( SELECT ID ,
DESC ,
TERMINATION_DATE ,
LAST_UPDATE ,
ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY LAST_UPDATE DESC ) SERIAL_ORDER
FROM LAST_UPDATE
) B
WHERE SERIAL_ORDER = 1

Related

How to select the min and max date from a table into another table on the same row? in SQL

So I have an example of a table like below:
ID
Category
AdmissionDate
DischargeDate
A1
A
2017-07-20
2017-07-21
A1
B
2017-07-27
2017-07-28
I would like to select the Min and Max date and also create two new columns based on the min and max date as below:
ID
MinAdmissionDate
MaxDischargeDate
AdmittedCategory
DischargeCategory
A1
2017-07-20
2017-07-28
A
B
The admitted category would be based on the MinAdmissionDate while the dischargeCategory would be based on the MaxDischargeDate
You could try joining to grouped table:
select
grouped.ID,
grouped.AdmissionDate,
grouped.DischargeDate,
admission.Category admissionCategory,
discharge.Category dischargeCategory
from
(
select
ID,
min(AdmissionDate) AdmissionDate,
max(DischargeDate) DischargeDate
from testTable
group by ID
) [grouped]
left join testTable [admission] on
[grouped].ID = [admission].ID and
[grouped].AdmissionDate = [admission].AdmissionDate
left join testTable [discharge] on
[grouped].ID = [discharge].ID and
[grouped].DischargeDate = [discharge].DischargeDate
Database fiddle.
Try something like this:
WITH cte As
(
SELECT
ID,
Category,
AdmissionDate,
DischargeDate,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY AdmissionDate) As ARN,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY DischargeDate DESC) As DRN
FROM
YourTable
)
SELECT
A.ID,
A.AdmissionDate As MinAdmissionDate,
D.DischargeDate As MaxDischargeDate,
A.Category As AdmittedCategory,
D.Category As DischargeCategory
FROM
cte As A
INNER JOIN cte As D
ON D.ID = A.ID
And A.ARN = 1
And D.DRN = 1
;
Demo
ROW_NUMBER

Select second latest date for each group in the table

hi guys for a report I need to find the second latest date for every specific SKU
down below is the code I am working with.
this is a simplified example.
SKU | plannendstartinflow
11538 2015-03-12
11538 2016-03-12
11538 2017-03-12
33252 2018-02-17
what i need to become is this because it is the second latest date of that SKU
SKU | plannendstartinflow
11538 2016-03-12
code below is the code that is used right now for the latest date
update :
select * from
(select
case when DATEDIFF(MONTH,MAX(PlannedEndInflow),GETDATE()) > 3 then max(PlannedEndInflow) else null end as datum
--case when DATEDIFF(MINUTE,od.PlannedEndInflow,Max(od.PlannedEndInflow)) > 1 then max(od.PlannedEndInflow) else null end as test
,od.odscheduleid
,lc.shortname as line
,ar.erpcode as SKU
,ar.shortname as Article
,od.PlannedEndInflow
,od.[PlannedEndInflow] as second_max_date
,Max(od.PlannedEndInflow) as max_date
,st.shortname as 'status'
,od.[ShortName] as 'order'
,od.[ERPCode]
,od.[ASCode]
,od.[PlannedQuantity] as 'PlannedQuantity [PC]'
,cast(od.[PlannedQuantity]*ar.Volume/100 as decimal(12,2)) as 'PlannedQuantity [HL]'
,od.[PlannedChangeoverTime]
,od.[PlannedSpeed]
,od.[PlannedSpeedRatio],
ROW_NUMBER()over(partition by ar.erpcode order by od.PlannedEndInflow desc) as rn
from(
[RM].[TblDatODSchedule] od
inner join [EM].[TblLstLocation] lc on od.locationid=lc.locationid
inner join [RM].[TblLstART] ar on od.artid=ar.artid
inner join [EM].[TblLstStatus] st on od.statusid=st.statusid
)
--where lc.shortname = 'lb1' and PlannedEndOutflow > '20190101'
group by
ar.ERPCode , lc.ShortName,od.odscheduleid,ar.shortname
,od.[PlannedStartInflow]
,od.[PlannedEndInflow]
,st.shortname
,od.[ShortName]
,od.[ERPCode]
,od.[ASCode]
,od.[PlannedQuantity]
,ar.Volume
,od.[PlannedChangeoverTime]
,od.[PlannedSpeed]
,od.[PlannedSpeedRatio]
) t2 where rn=2;
thanks in advance
You can use the following code to get the second latest date:
select * from
(select SKU,plannendstartinflow,
ROW_NUMBER()over(partition by SKU order by plannendstartinflow desc) as rn
from test
)t where rn=2;
EDIT:
select * from
(select SKU,plannendstartinflow, --similarly add other columns
ROW_NUMBER()over(partition by SKU order by plannendstartinflow desc) as rn
from (
--Put Your Subquery here
)t1
)t2 where rn=2;
EDIT2: To select max and second max date.
select SKU,min(plannendstartinflow) as secondmaxdate,max(plannendstartinflow) as
maxdate from
(select * from (select SKU,plannendstartinflow,
ROW_NUMBER()over(partition by SKU order by plannendstartinflow desc) as rn
from test
)t where rn<3
)t1 group by SKU;

Select the Max date time for single User

I have a table like this,
Date User
15-06-2018 A
16-06-2018 A
15-06-2018 B
14-06-2018 C
16-06-2018 C
I want to get the output like this,
Date User
16-06-2018 A
15-06-2018 B
16-06-2018 C
I tried Select Max(date),User from Table group by User
Based on your comment, I assume you have duplicated results in those 80 columns when you group by them. Assuming so, here's one option using row_number to always return 1 row per user:
select *
from (
select *, row_number() over (partition by user order by date desc) rn
from yourtable
) t
where rn = 1
You can use correlation subquery :
select t.*
from table t
where date = (select max(t1.date)
from table t1
where t1.user = t.user
);
However, i would also recommend row_number() :
select top (1) with ties *
from table t
order by row_number() over (partition by user order by date desc);
You can also use a ranking function
SELECT User, Date
FROM
(
SELECT User, Date
, Row_id = Row_Number() OVER (Partition by User, ORDER BY User, Date desc)
FROM table
)q
WHERE Row_Id = 1
I would suggest you this
Select * from table t where exist
(Select 1 from
(Select user, max(date) as date from table) A
Where A.user = t.user and A.date = t.date )

Filter the table with latest date having duplicate OrderId

I have following table:
I need to filter out the rows for which start date is latest corresponding to its order id .With reference to given table row no 2 and 3 should be the output.
As row 1 and row 2 has same order id and order date but start date is later than first row. And same goes with row number 3 and 4 hence I need to take out row no 3 . I am trying to write the query in SQL server. Any help is appreciated.Please let me know if you need more details.Apologies for poor English
You can do this easily with a ROW_NUMBER() windowed function:
;With Cte As
(
Select *,
Row_Number() Over (Partition By OrderId Order By StartDate Desc) RN
From YourTable
)
Select *
From Cte
Where RN = 1
But I question the StartDate datatype. It looks like these are being stored as VARCHAR. If that is the case, you need to CONVERT the value to a DATETIME:
;With Cte As
(
Select *,
Row_Number() Over (Partition By OrderId
Order By Convert(DateTime, StartDate) Desc) RN
From YourTable
)
Select *
From Cte
Where RN = 1
Another way using a derived table.
select
t.*
from
YourTable t
inner join
(select OrderId, max(StartDate) dt
from YourTable
group by OrderId) t2 on t2.dt = t.StartDate and t2.OrderId = t.OrderId

Group by with MIN value in same query while presnting all other columns

I have a view called a with this data:
ID tDate name task val
23 2015-06-14
23 2015-06-25
126 2015-06-18
126 2015-06-22
126 2015-06-24
ID is integer and tDate is timestamp.
Basically I want to get for each ID the min value of tDate and present this row.
meaning:
ID tDate name task val
23 2015-06-14
126 2015-06-18
I wrote this query:
select ID, min(tDate)
from a
group by ID
order by ID
This is working BUT it doesn't allow me to present all other columns of a
for example if I do:
select ID, min(tDate), name
from a
group by ID
order by ID
it says that name must be under group by. So I wrote this query:
select ID, MIN(tDate), name, task, val , ....
from a
group by ID, name, task, val , ....
order by ID
And this one doesn't work. it gives false results.
How do I solve it?
Postgres has the very convenient distinct on for this type of problem:
select distinct on (id) a.*
from a
order by id, tdate;
This will return one row for each id. The row is the first one determined by the ordering defined in the order by clause.
Do a join from the one table to a sub-query table on just the ID / Min Date
select
YT.ID,
YT.tDate as OriginalDate,
PQ.MinDate,
YT.name,
YT.task,
YT.val
from
YourTable YT
JOIN ( select ID, min( tdate ) as MinDate
from YourTable
group by ID ) as PQ
on YT.ID = PQ.ID
AND YT.tDate = PQ.MinDate
order by
ID
Try something like this:
select a.id, a.tdate , .... from a
join (select id, min(tdate) min_date
from a
group by ID
) b
on a.id=b.id and a.tdate = b.min_date
order by a.id