活动表:
id user type creation_date update_date
1 A AAA 1111 3333
2 A BBB 2222 4444
3 A CCC 3333 5555
4 A DDD 4444 6666
5 B AAA 3333 4444
6 B BBB 4444 5555
7 B CCC 5555 6666
8 C AAA 2222 3333
9 C BBB 1111 7777
10 C CCC 3333 4444
11 C DDD 4444 9999
任务:
查找具有至少一个DDD事件的所有用户,并且creation_date的用户最新非DDD事件与update_date的最新非DDD事件不同。
所以对于上面的记录:
用户A有一个DDD事件。好。但是最后创建的非DDD事件和最后更新的非DDD事件是相同的(事件#3)。因此从结果集中排除。
用户B没有DDD事件。因此从结果集中排除。
用户C有一个DDD事件。最后创建的非DDD事件(#10)与上次更新的非DDD事件(#9)不同。因此包含在结果集中。
结果集:
user
C
我尝试了不同的东西,包括GROUP BY和EXISTS。但是我无法对每组记录进行排序。
有什么想法吗?
答案 0 :(得分:2)
这是一个更好的主意:
SELECT e.usr
FROM (SELECT usr FROM event WHERE type = 'DDD') u
JOIN event e USING (usr)
WHERE e.type <> 'DDD'
GROUP BY e.usr
HAVING NOT EXISTS (
SELECT 1 FROM event e0
WHERE e0.creation_date = max(e.creation_date)
AND e0.update_date = max(e.update_date)
AND e0.usr = e.usr
AND e0.type <> 'DDD'
)
ORDER BY 1;
这应该像现在一样简单快捷。如果您有正确的索引,那么 fly 。
我使用usr
代替user
,因为后者是标准SQL中的保留字。
在子查询u
中,获取至少有一行type = 'DDD'
的所有用户。
将此集合加入基表,使用不同的事件(type <> 'DDD
)获取同一用户的所有行。
在HAVING
子句中,排除有最新creation_date
行和最新update_date
行的情况。
此查询甚至可与基表中的重复项一起使用。
较慢而不聪明:
SELECT e.usr
FROM (SELECT usr FROM event WHERE type = 'DDD') u
JOIN event e USING (usr)
WHERE e.type <> 'DDD'
GROUP BY e.usr
HAVING (SELECT id FROM event WHERE creation_date = max(e.creation_date) AND usr = e.usr AND type <> 'DDD')
<> (SELECT id FROM event WHERE update_date = max(e.update_date ) AND usr = e.usr AND type <> 'DDD')
ORDER BY 1
答案 1 :(得分:1)
我仍然想知道这是否可以简化,但你可以使用它:
SELECT DISTINCT user
FROM yourtable
WHERE user NOT IN (
SELECT user
FROM yourtable t1
WHERE
EXISTS (
SELECT NULL
FROM yourtable t2
WHERE t2.type!='DDD' AND t1.user=t2.user
GROUP BY user
HAVING max(t2.creation_date)=t1.creation_date
AND max(t2.update_date)=t1.update_date)
)
AND EXISTS (SELECT null
FROM yourtable t2
WHERE t2.user=yourtable.user
AND type='DDD')
请参阅小提琴here。