使用GROUP BY为相应的最大日期选择ID

时间:2018-11-27 08:54:44

标签: sql-server tsql group-by

我的表结构如下

Category    Sex         Last Modified Date          Id
7           2           2015-01-16                  87603
7           1           2014-11-27                  87729
7           2           2018-09-06                  87135
7           1           2017-12-27                  87568

我的SQL查询如下

SELECT
    MAX(Id) AS Id
FROM 
    Table
GROUP BY 
    Category, Sex

结果如下

87603
87729

但是我想获得 Id 作为“上次修改日期”。正确的结果应如下所示

87135
87568

5 个答案:

答案 0 :(得分:2)

您可以使用ROW_NUMBER()查找每个组的最新行:

SELECT Id, LastModifiedDate
FROM (
    SELECT Id, LastModifiedDate, ROW_NUMBER() OVER (PARTITION BY Category, Sex ORDER BY LastModifiedDate DESC) AS rnk
    FROM t
) AS cte
WHERE rnk = 1

如果您有兴趣查找所有与LastModifiedDate有联系的行,请使用RANK()

答案 1 :(得分:1)

您也可以将其作为

SELECT T.*
FROM
    (
      SELECT Sex,
             MAX([Last Modified Date]) [Last Modified Date],
             Category
      FROM T
      GROUP BY Sex,
            Category
    ) TT INNER JOIN T ON T.[Last Modified Date] = TT.[Last Modified Date]
WHERE T.Sex = TT.Sex
      AND
      T.Category = TT.Category;

返回:

+----------+-----+---------------------+-------+
| Category | Sex | Last Modified Date  |  Id   |
+----------+-----+---------------------+-------+
|        7 |   2 | 06/09/2018 00:00:00 | 87135 |
|        7 |   1 | 27/12/2017 00:00:00 | 87568 |
+----------+-----+---------------------+-------+

答案 2 :(得分:1)

我们可以通过将同一张表及其分组集结合在一起来获得解决方案:

SELECT MIN(T.Id)
FROM Table T
INNER JOIN (SELECT  Category, 
                    Sex,
                    MAX(LastModifiedDate) AS LastModifiedDate
            FROM Table
            GROUP BY Category, Sex) GT 
            ON GT.Category = T.Category
            AND GT.Sex = T.Sex
            AND GT.LastModifiedDate = T.LastModifiedDate
GROUP BY T.Category, T.Sex

答案 3 :(得分:1)

其他选项是使用 correlated 子查询:

select t.*
from table t
where t.LastModifiedDate = (select max(t1.LastModifiedDate) 
                            from table t1 
                            where t1.Category = t.Category and t1.Sex = t.Sex
                           );

答案 4 :(得分:1)

以下是几种不同的方法...(无特定顺序)

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData;
GO

CREATE TABLE #TestData (
    Category TINYINT NOT NULL,
    Sex TINYINT NOT NULL,
    LastModifiedDate DATE NOT NULL,
    Id INT NOT NULL 
    );
GO

INSERT #TestData(Category, Sex, LastModifiedDate, Id) VALUES 
    (7, 2, '2015-01-16', 87603),
    (7, 1, '2014-11-27', 87729),
    (7, 2, '2018-09-06', 87135),
    (7, 1, '2017-12-27', 87568);
GO 

/* nonclustered index to support the query. */
CREATE UNIQUE NONCLUSTERED INDEX ix_TestData_Category_Sex_LastModifiedDate
    ON #TestData (Category ASC, Sex ASC, LastModifiedDate DESC)
    INCLUDE (Id);
GO 

--====================================================

-- option 1: TOP(n) WITH TIES...
SELECT TOP (1) WITH TIES
    td.Id
FROM
    #TestData td
ORDER BY 
    ROW_NUMBER() OVER (PARTITION BY td.Category, td.Sex ORDER BY td.LastModifiedDate DESC);
GO 

-----------------------------------------------------

-- option 2: Filter on ROW_NUMBER()...
WITH 
    cte_AddRN AS (
        SELECT 
            td.Id,
            rn = ROW_NUMBER() OVER (PARTITION BY td.Category, td.Sex ORDER BY td.LastModifiedDate DESC)
        FROM
            #TestData td
        )
SELECT 
    arn.Id
FROM
    cte_AddRN arn
WHERE 
    arn.rn = 1;
GO 

-----------------------------------------------------

-- option 3: binary concatination...
SELECT 
    Id = CONVERT(INT, SUBSTRING(MAX(bv.bin_val), 4, 4))
FROM
    #TestData td
    CROSS APPLY ( VALUES (CONVERT(BINARY(3), td.LastModifiedDate) + CONVERT(BINARY(4), td.Id)) ) bv (bin_val)
GROUP BY 
    td.Category,
    td.Sex;
GO 

--====================================================