如何使用MS SQL获取包含组的Max列?

时间:2016-12-07 09:14:13

标签: sql sql-server

我想要查询的是“获取用户的最后致命日志”。当我查询下面的语句时它只返回“username”和“logDate”字段,但我也想得到这个“logDate”的相应行(我的意思是logid,logdata);

SELECT user.username, MAX(log.logDate) FROM user 
INNER JOIN log ON user.userid = log.userid
WHERE log.logtype = 'fatal'
GROUP BY user.username

我的用户表;

userid  username   
-----------------
1       robert
2       ronaldo

日志表;

logid  logDate                    logtype  userid  logdata
----------------------------------------------------------
1      2016-11-28 19:37:53.000    fatal    1       data
2      2016-11-28 22:37:53.000    fatal    1       data
3      2016-11-28 12:37:53.000    fatal    2       data

4 个答案:

答案 0 :(得分:4)

我将使用CROSS APPLY执行此操作(首选方法并将适当的索引添加到Log表)

SELECT *
FROM   [USER] u
       CROSS apply (SELECT TOP 1 *
                    FROM   log l
                    WHERE  u.userid = l.userid
                           AND l.logtype = 'fatal'
                    ORDER  BY l.logDate DESC) cs

如果log表非常大,那么在Log表上创建Non Clustered Index以提高性能

CREATE NONCLUSTERED INDEX NIX_Log_logtype_userid
ON [log] (logtype,userid)
INCLUDE (logid,logDate,logdata)

使用ROW_NUMBER

的另一种方法
SELECT *
FROM   (SELECT *,
               Row_number()OVER(partition BY [USER].username ORDER BY log.logDate DESC) AS rn
        FROM   [USER]
               INNER JOIN log
                       ON [USER].userid = log.userid
        WHERE  log.logtype = 'fatal') A
WHERE  rn = 1 

使用ROW_NUMBERTOP 1 with ties

的另一种方法
SELECT TOP 1 WITH ties *
FROM   [USER]
       INNER JOIN log
               ON [USER].userid = log.userid
WHERE  log.logtype = 'fatal'
ORDER  BY Row_number()OVER(partition BY [USER].username ORDER BY log.logDate DESC) 

注意:所有查询都会导致两个表中的所有列都选择所需的列

答案 1 :(得分:2)

快速选项是在子查询中获取max logdate。这样,您可以从用户表中选择所需的任何字段,而不必在外部查询中进行聚合。这个问题的唯一问题是你的logdate不需要重复。如果它是一个日期时间,那么这不太可能,但如果它只是一个日期字段,您可能会有重复项。值得一试。

SELECT
     u.username
    ,u.logdate
    ,u.logid
    ,u.logdata
FROM user u
INNER JOIN (SELECT 
                userid
                ,MAX(logdate) MaxLog 
            FROM log 
            WHERE logtype = 'fatal' 
            GROUP BY userid) l
    ON u.userid = l.userid
    AND u.logdate = l.MaxLog

答案 2 :(得分:2)

您可以使用ROW_NUMBER

a

答案 3 :(得分:0)

WITH MaxLogDate AS (
    SELECT user.userid, MAX(log.logDate) logDate FROM user 
    INNER JOIN log ON user.userid = log.userid
    WHERE log.logtype = 'fatal'
    GROUP BY user.userid
)
SELECT log.logid, log.logDate, log.logtype, u.userid, u.username
FROM user u
    JOIN MaxLogDate m ON u.userid = m.userid  
    JOIN log ON log.logDate = m.logDate AND log.userid = m.userid 
WHERE log.logtype = 'fatal' --This line is optional, may increase the performance.