1

我正在为应该是一个简单的查询而苦苦挣扎。

事件表存储应用程序中的用户活动。每次单击都会生成一个新事件和日期时间戳。我需要显示具有最新日期时间戳的最近访问记录的列表。我只需要显示过去 7 天的活动。

该表有一个自增字段 (eventID),与 date_event 字段相对应,因此最好使用它来确定组中的最新记录。

我发现某些记录没有以预期的最近日期时间出现在我的结果中。所以我把我的查询去掉了基础:

请注意,现实生活中的查询不会查看 custID。我把它包括在这里是为了缩小问题的范围。

        SELECT
            el.eventID,
            el.custID,
            el.date_event
        FROM  
            event_log el
        WHERE 
            el.custID = 12345 AND
            el.userID=987
        GROUP BY  
            el.custID
        HAVING
            MAX( el.eventID )

这是返回的:

eventID     custID  date_event
346290      12345   2013-06-21 09:58:44

这是解释

id  select_type     table   type    possible_keys               key     key_len     ref     rows    Extra
1   SIMPLE          el      ref     userID,custID,Composite     custID  5           const   203     Using where

如果我将查询更改为使用 HAVING MIN,结果不会改变。我应该会看到不同的 eventID 和 date_event,因为有数十条记录与 custID 和 userID 匹配。

        SELECT
            el.eventID,
            el.custID,
            el.date_event
        FROM  
            event_log el
        WHERE 
            el.custID = 12345 AND
            el.userID=987
        GROUP BY  
            el.custID
        HAVING
            MIN( el.eventID )

结果与之前相同:

eventID     custID  date_event
346290      12345   2013-06-21 09:58:44

没变。

这告诉我我还有另一个问题,但我没有看到可能是什么。

一些指针将不胜感激。

4

2 回答 2

3
SELECT
    el.eventID,
    el.custID,
    el.date_event
FROM  
    event_log el
WHERE 
    el.custID = 12345 AND
    el.userID=987 AND
    el.eventID IN (SELECT MAX(eventID)
                   FROM event_log
                   WHERE custID = 12345
                   AND userID = 987)

您的查询不起作用,因为您误解了什么HAVING。它计算结果集中每一行的表达式,并保留表达式计算结果为真的行。该表达式MAX(el.eventID)仅返回查询选择的最大事件 ID,它不会将当前行与该事件 ID 进行比较。

另一种方法是:

SELECT
    el.eventID,
    el.custID,
    el.date_event
FROM  
    event_log el
WHERE 
    el.custID = 12345 AND
    el.userID=987
ORDER BY eventID DESC
LIMIT 1

适用于多个 custID 的更通用形式是:

SELECT el.*
FROM event_log el
JOIN (SELECT custID, max(date_event) maxdate
      FROM event_log
      WHERE userID = 987
      GROUP BY custID) emax
ON el.custID = emax.custID AND el.date_event = emax.maxdate
WHERE el.userID = 987
于 2013-06-28T21:02:06.163 回答
0

您可以在不包含 GROUP BY 子句的语句中使用组函数,但这相当于对所有行进行分组。但我猜你正在寻找通用语法,

SELECT
  MIN(el.eventID) AS `min_eventID`, --> Yes it is wrong :(
  el.custID,
  el.date_event
FROM  
  event_log el
WHERE 
  el.userID = 987
GROUP BY el.custID;

但欢迎有不同意见。


[ 编辑 ]

我认为我没有足够快地展示解决方案......但也许您正在寻找最快的解决方案。
假设date_event字段默认为 CURRENT_TIMESTAMP(我错了吗?),按 date_event 排序将浪费时间(因此浪费金钱)。
我用 20K 行做了一些测试,执行时间大约是 5ms。

SELECT STRAIGHT_JOIN y.*
FROM ((
  SELECT MAX(eventId) as eventId
  FROM event_log
  WHERE userId = 987 AND custId = 12345
)) AS x
INNER JOIN event_log AS y
  USING (eventId);

也许(可能,谁知道)你没有得到 straight_join 的东西;正如经文中记载的那样,STRAIGHT_JOIN 类似于 JOIN,除了左表总是在右表之前读取。有时它很有用。
对于您的具体情况,我们可能会过滤到某个 eventID 之前(在表“x”上),而不是从表“y”中检索 99.99% 无用的行。

  • 预计在 3、2、... 中会出现更多分歧
于 2013-06-28T21:02:15.157 回答