简体   繁体   中英

How do I get the top 1 row from each group? (T-SQL)

I have a table that looks like this:

ID    Month    Year
 1      3       2016
 1      5       2016
 1      2       2016
 2      3       2016
 2      1       2015
 2      NULL    NULL
 3      NULL    NULL
etc...

I want to select 1 row per id with the max year and then month or NULL if there is no other choice so an outcome like this:

ID    Month    Year
1      5       2016
2      3       2016
3      NULL    NULL

Here is what my current query looks like:

SELECT distinct
LogTable.CaseID,
Monthlies.Month,
Monthlies.Year
FROM [LogTable]
LEFT JOIN CTable
on LogTable.SerialNum = CTable.SERIAL_NUM
LEFT JOIN 
tCaseStatus AS CaseStatus ON CaseStatus.CaseGUID = LogTable.CaseGUID LEFT JOIN
tReferredBy AS ReferredBy ON ReferredBy.ReferredByGUID =   LogTable.ReferredByGUID LEFT JOIN
placements AS Placement ON Placement.LogGUID = LogTable.LogGUID LEFT JOIN
PlacementMonth AS Monthlies ON Monthlies.PlacementRowGUID = Placement.PlacementRowGUID LEFT JOIN
tRC AS RC ON RC.RCGUID = LogTable.RCGUID LEFT JOIN
VendorH ON VendorH.LogGUID = LogTable.LogGUID LEFT JOIN
tVendor AS Vendor ON Vendor.VendorGUID = VendorH.VendorGUID 
where CaseStatus.Name = 'Active'
order by Monthlies.Year DESC , Monthlies.Month desc

I have tried doing a outer apply on the table that the month and year from to select the top 1st row on a desc month and year inside the outer apply but I get multiple rows for some Ids.

This kind of request can be handled using ROW_NUMBER

select * from 
(
select row_number() over(partition by ID order by [year] desc,[month] desc) as rn,*
From yourresult
) A
Where RN = 1
with CTE as
(
select ID, Month, Year, row_number() over(partition by ID order by Year desc, Month desc) as ROW_ORD
from Table1
)
select ID, Month, Year
from CTE
where ROW_ORD = 1

Firstly, I'd avoid column names that are keywords in SQL if possible, ie Month and Year. You can achieve what you're after using:

ROW_NUMBER :

Returns the sequential number of a row within a partition of a result set, starting at 1 for the first row in each partition.

Runnable sample:

CREATE TABLE #LogTable
    (
      [ID] INT ,
      [Month] INT ,
      [Year] INT
    );

INSERT  INTO #LogTable
        ( [ID], [Month], [Year] )
VALUES  ( 1, 3, 2016 ),
        ( 1, 5, 2016 ),
        ( 1, 2, 2016 ),
        ( 2, 3, 2016 ),
        ( 2, 1, 2015 ),
        ( 2, NULL, NULL ),
        ( 3, NULL, NULL );

SELECT  t.ID ,
        t.Month ,
        t.Year
FROM    ( SELECT    ID ,
                    [Month] ,
                    [Year] ,
                    ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY [Year] DESC, [Month] DESC ) row
          FROM      #LogTable
        ) t
WHERE   t.row = 1

DROP TABLE  #LogTable

Produces:

ID  Month   Year
1   5       2016
2   3       2016
3   NULL    NULL

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM