如何在约束的情况下查询数据库以查找给定日期内每个用户的最后一个条目?

时间:2012-01-19 15:45:01

标签: mysql sql

我正在查询MySQL数据库中的一个非常大的活动日志,试图弄清楚每个用户在某一天的午夜做了什么。问题是我只对可能的日志消息的子集感兴趣,并且我希望在午夜之前该子集中的最后一个日志条目。这是我到目前为止所做的:

SELECT user, dateAndTime, msg
FROM Log
WHERE msg in ('off', 'on', 'sleep', 'wake')
  AND logDate = '2011-12-31';
ORDER BY user ASC, dateAndTime DESC

(我们将用户和消息称为类型VARCHAR,将日期定义为DATE,将dateAndTime定义为DATETIME。)

这似乎是一个很好的第一步。结果按用户名显示在组中,并按时间排序。 有没有办法为每个用户提供这些结果的第一行?我总是可以对结果进行后期处理,但这似乎是我应该能够对查询本身做的事情。我很想在集合中而不是在程序上思考,所以如果解决方案应该是显而易见的,我会事先道歉。

附加说明......

我在SO上发现了许多其他问题来处理同样的问题,但是我的额外限制使得它变得更加困难。我尝试修改this query,但我认为GROUP BY条款在某种程度上失去了对msg的限制。

我也在时间限制下工作。查询通过一个Web服务(我无法控制),在5分钟后自动超时。 Log表很大(2011-12-31只有近200万行),因此我尝试涉及的大多数解决方案只是超时。

更新

我发现了一些我之前不知道的数据。对于给定的dateAndTime每个用户有多行

3 个答案:

答案 0 :(得分:4)

SELECT l.user, l.dateAndTime, l.msg
    FROM Log l
        INNER JOIN (SELECT user, MAX(dateAndTime) AS MaxDateTime
                        FROM log
                        WHERE msg in ('off', 'on', 'sleep', 'wake')
                            AND logDate = '2011-12-31'
                        GROUP BY user) q
            ON l.user = q.user
                AND l.dateAndTime = q.MaxDateTime
    WHERE l.msg in ('off', 'on', 'sleep', 'wake')
    ORDER BY l.user ASC

答案 1 :(得分:1)

警告:保证始终有效,但应该很快:

select * from
(SELECT user, dateAndTime, group_concat(msg) allMsgs
 FROM Log
 WHERE msg in ('off', 'on', 'sleep', 'wake')
   AND logDate = '2011-12-31'
 GROUP BY user, dateAndTime
 ORDER BY user ASC, dateAndTime DESC) v
group by user

在MySQL中,既不聚合也不分组的列仍可包含在分组查询的select子句中。根据MySQL文档,这些列不是保证是组中任何特定行的值(因为这是一个包含功能依赖于 em>分组),但通常似乎是组内访问的第一个值。此功能很容易受到查询计划中的更改的影响,这就是为什么所有排序都在内联视图中进行的原因 - 因此分组应该发生在查询部分之外,可以通过查询计划中的更改进行更改。

答案 2 :(得分:0)

SELECT log.user, log.msg, log.dateAndTime 
FROM(
  SELECT user, msg, max(dateAndTime) as maxdatetime
  FROM Log
  WHERE msg in ('off', 'on', 'sleep', 'wake')
    AND logDate = '2011-12-31';
  GROUP BY user, msg    
) inner, Log log
WHERE log.user = inner.user 
AND log.msg = inner.msg 
AND log.dateAndTime = inner.maxdatetime
ORDER BY log.user ASC, log.dateAndTime DESC