Click here to Skip to main content
15,887,135 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
The table is like:

EmpID    Name    Date1         Date2
1      A       30/Jan/2021  20/Jan/2021
1      A       29/Jan/2021  20/Jan/2021
2      B       Null         20/Jan/2021
2      B       NUll         21/Jan/2021
3      C       28/Jan/2021  21/Jan/2021


The code should return a result like:

EmpID      Name      Date1
1          A         30/Jan/2021
2          B         null
3          c         28/Jan/2021


The requirement is to first identify max date2 for each employee, max date1 and that should also have null record.

I have tried with two max subqueries with each date with self join. it works but it is not including the record where Date1 is null.

I can get it done using CTE with partition by to include null but that is for one date only.

What I have tried:

select id,name,date1 from Table T1
where date2=(select max(date2) from Table T2 where t1.name=t2.name)
and date1= (select max(date1) from Table T2 where t1.name=t2.name)

It is not including the record where Date1 is null.
Posted
Updated 19-Aug-21 23:11pm
v2

Use GROUP BY and the MAX aggregate function to identify the records, then use a JOIN to combine them back with the original data.
SQL
SELECT m.* FROM MyTable m
JOIN (SELECT ID, MAX([Date]) As MaxDate FROM MyTable
      GROUP BY ID) g
  ON m.ID = g.ID AND m.[Date] = g.MaxDate
 
Share this answer
 
v2
Comments
Maciej Los 19-Aug-21 3:05am    
5ed!
The following query will give you the expected output for your sample input:
SQL
WITH cte As
(
    SELECT
        EmpID,
        Name,
        Date1,
        ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY Date2 DESC) As RN
    FROM
        YourTable
)
SELECT
    EmpID,
    Name,
    Date1
FROM
    cte
WHERE
    RN = 1
;
Output:
EmpID | Name | Date1
=========================
    1 |    A | 2021-01-30
    2 |    B | NULL
    3 |    C | 2021-01-28
However, you mention that you've already done something like that "for one date only".

But you haven't explained what is wrong with that output.
 
Share this answer
 
Comments
Maciej Los 19-Aug-21 3:05am    
5ed!
PreetMDX 20-Aug-21 4:36am    
Thank Richard,

The problem is that this is not actually grouping the max dates by name.

suppose the data is like:
EmpID Name Date1 Date2
1 A 29/Jan/2021 20/Jan/2021
1 A 30/Jan/2021 20/Jan/2021
2 B Null 20/Jan/2021
2 B NUll 21/Jan/2021

The output this query returns based on date order defined in row number.
It returns what row of Date1 comes first.
If the Date2 has same dates for a name as shown above. It would fetch the corresponding date from Date1 column which is

EmpID Name Date1
1 A 29/Jan/2021
2 B null

However it should be 30/Jan/2021 for name A.
Richard Deeming 20-Aug-21 6:00am    
In that case, change the ordering for the row number:
ROW_NUMBER() OVER (PARTITION BY EmpID ORDER BY Date2 DESC, Date1 DESC) As RN
PreetMDX 26-Aug-21 2:21am    
Thanks Richard, Changing the order did fix that issue as well:)
Not sure if I understand the requirement correctly but from what I gather you first need to find the rows for each empid containing max based on date2 and then from this set the rows having max of date1 per each empid.

If this was correct interpretation, you could consider something like this
First the example data
SQL
create table ta1 (
   empid int,
   name  varchar(10),
   date1 date,
   date2 date
);

insert into ta1 (EmpID, Name, Date1, Date2) values 
(1, 'A', '30/Jan/2021', '20/Jan/2021'),
(1, 'A', '29/Jan/2021', '20/Jan/2021'),
(2, 'B', Null,          '20/Jan/2021'),
(2, 'B', NUll,          '21/Jan/2021'),
(3, 'C', '28/Jan/2021', '21/Jan/2021');

Now let's get the rows having max date2 for each emp. The query could look like this
SQL
WITH Date2Query AS (
   SELECT t1.empid, 
          t1.name, 
		  t1.date1,
		  t1.date2
   FROM ta1 T1
   WHERE t1.date2 = (select max(t2.date2) 
                     from ta1 T2 
					 where t1.name = t2.name)
)
SELECT * FROM Date2Query;

so the result would be
empid name date1      date2
3     C    2021-01-28 2021-01-21
2     B    NULL	      2021-01-21
1     A    2021-01-30 2021-01-20
1     A    2021-01-29 2021-01-20

Now to get the rows for each emp having max of date1 you can use the approach you already tried but in case of null, use a non-existent date in the comparison to ensure that if max is null then the comparison is true. For example using COALESCE the query could look like this
SQL
WITH Date2Query AS (
   SELECT t1.empid, 
          t1.name, 
		  t1.date1,
		  t1.date2
   FROM  ta1 T1
   WHERE t1.date2 = (SELECT max(t2.date2) 
                     from ta1 T2 
					 where t1.name = t2.name)
)
SELECT t1.empid, 
       t1.name, 
       t1.date1
FROM Date2Query T1
WHERE COALESCE(t1.date1,'01/01/1900') 
      = COALESCE((SELECT MAX(t2.date1) 
                  FROM Date2Query T2 
				  WHERE t1.name = t2.name),'01/01/1900') ;

And the result is
empid name date1
3     C    2021-01-28
2     B    NULL
1     A    2021-01-30

This can be re-written in several ways. One option is to fetch NULL's and non-NULL's separately, for example
SQL
WITH Date2Query AS (
   SELECT t1.empid, 
          t1.name, 
		  t1.date1,
		  t1.date2
   FROM  ta1 T1
   WHERE t1.date2 = (SELECT max(t2.date2) 
                     from ta1 T2 
					 where t1.name = t2.name)
)
SELECT t1.empid, 
       t1.name, 
       t1.date1
FROM Date2Query T1
WHERE t1.date1 = (SELECT MAX(t2.date1) 
                  FROM Date2Query T2 
				  WHERE t1.name = t2.name)
UNION ALL
SELECT t1.empid, 
       t1.name, 
       t1.date1
FROM Date2Query T1
WHERE t1.date1 IS NULL;
 
Share this answer
 
Comments
Maciej Los 19-Aug-21 3:06am    
5ed!
Wendelius 22-Aug-21 6:09am    
Thanks
PreetMDX 20-Aug-21 5:00am    
Thank you @wendelius, Your understanding is absolutely correct on this and the solution works like charm.
The missing link was coalesce function.
Wendelius 22-Aug-21 6:09am    
Glad you got it working!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900