我正在努力应该做一个简单的查询。
事件表在应用程序中存储用户活动。每次单击都会生成一个新事件和日期时间戳。我需要显示最近访问的记录列表,其中包含最新的日期时间戳。我只需要显示过去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
这是EXPLAIN
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
没有变化。
这告诉我我有另一个问题,但我没有看到可能是什么。
一些指示将不胜感激。
答案 0 :(得分: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
的作用。它计算结果集每一行的表达式,并将表达式计算结果的行保持为true。表达式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
答案 1 :(得分: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);
也许(可能,谁知道)你没有得到直接的东西;如scriptures所述,STRAIGHT_JOIN类似于JOIN,但左表始终在右表之前读取。有时它很有用。
对于您的具体情况,我们可能会在(表“x”)之前过滤到某个eventID,而不是从表“y”中检索99,99%无用的行。