Home > Software design >  If multiple records come, get row with latest date
If multiple records come, get row with latest date

Time:08-05

I have a table

Admission_Letter_Log_ID | URL    |  Letter_Generation DateTime |   Admission Letter Template ID
       97               some URL     2021-10-08 06:46:53.567         23
       98               some URL     2021-10-08 06:50:03.887         23
       99               some URL     2021-10-08 06:53:29.857         24
       100              some URL     2021-10-08 06:54:54.303         25

I want to get Admission_Letters but if they have same Admission Letter Template ID, return one with the latest Letter generation Date time.

What I have tried:

select Admission_Letter_Template_ID ,max(Letter_Generation_Datetime) FROM 

CoC_Admission_Letter_Log ccall 
where Admission_Application_Master_ID=4487
group by Admission_Letter_Template_ID 

Which returns:

Admission_Letter_Template_ID|                       |
---------------------------- ----------------------- 
                          23|2022-08-03 07:38:53.087|
                          27|2022-08-03 07:41:32.287|

It works fine because similar Admission Letter Template ID are returning one with latest Date time but I also want Admission_Letter_Log_ID so instead I try this:

select Admission_Letter_Log_ID,Admission_Letter_Template_ID ,max(Letter_Generation_Datetime) FROM CoC_Admission_Letter_Log ccall 
where Admission_Application_Master_ID=4487
group by Admission_Letter_Log_ID,Admission_Letter_Template_ID 

which returns:

Admission_Letter_Log_ID|Admission_Letter_Template_ID|                       |
----------------------- ---------------------------- ----------------------- 
                    116|                          23|2022-08-02 06:32:46.990|
                    117|                          23|2022-08-03 07:38:53.087|
                    118|                          27|2022-08-03 07:41:32.287|

But now my Admission Letter Template ID again are coming as duplicate, instead of returning duplicate ones as one with max dateTime.

TLDR; I want to return this

Admission_Letter_Log_ID|Admission_Letter_Template_ID|                       |
----------------------- ---------------------------- ----------------------- 
                    117|                          23|2022-08-03 07:38:53.087|
                    118|                          27|2022-08-03 07:41:32.287|

CodePudding user response:

You get both rows because the value for Admission_Letter_Log_ID differs in both rows, just like with Letter_Generation_Datetime

So, remove Admission_Letter_Log_ID from the group by, and also use the max function on Admission_Letter_Log_ID

select max(Admission_Letter_Log_ID) as Admission_Letter_Log_ID,
       Admission_Letter_Template_ID,
       max(Letter_Generation_datetime) as Letter_Generation_Datetime
FROM   ccall 
where  Admission_Application_Master_ID = 4487
group by Admission_Letter_Template_ID 

See this DBFiddle

Admission_Letter_Log_ID Admission_Letter_Template_ID Letter_Generation_Datetime
117 23 2021-10-08 06:50:03.887
118 27 2022-08-03 07:41:32.287

EDIT

As commented by @ThorstenKettner I assumed that a greater Letter_Generation_datetime always means a greater Admission_Letter_Log_ID.
If this is not the case, than another approach is to subquery the grouping and then join on that result, see this query

select c2.Admission_Letter_Log_ID,
       t.Admission_Letter_Template_ID,
       t.Letter_Generation_Datetime
from  ( select c.Admission_Letter_Template_ID,
               max(c.Letter_Generation_datetime) as Letter_Generation_Datetime
        from   ccall c
        where  Admission_Application_Master_ID = 4487
        group by Admission_Letter_Template_ID 
     ) t
  join ccall c2 on t.Admission_Letter_Template_ID = c2.Admission_Letter_Template_ID
               and t.Letter_Generation_Datetime = c2.Letter_Generation_Datetime

And also see this new DBFiddle

CodePudding user response:

try this with sub query

select * from ccall where Admission_Letter_Log_ID in (select Max(ct.Admission_Letter_Log_ID)
FROM   ccall ct
where  ct.Admission_Application_Master_ID = 4487 
group by ct.Admission_Letter_Template_ID 
)

CodePudding user response:

If multiple records come, get row with latest date

This means you don't want to aggregate your data, but simply filter it, i.e. pick the rows to select. One way to do this is by using a window function:

select 
  admission_letter_log_id, url, letter_generation_datetime, admission_letter_template_id
from
(
  select
    coc_admission_letter_log.*,
    max(letter_generation_datetime)
      over (partition by admission_letter_template_id) as max_dt
  from coc_admission_letter_log
  where admission_application_master_id = 4487
) ccall
where letter_generation_datetime = max_dt
order by admission_letter_template_id;

Or:

select top (1) with ties *
from coc_admission_letter_log
where admission_application_master_id = 4487
order by row_number() over (partition by admission_letter_template_id
                            order by letter_generation_datetime desc)
  • Related