0

事件表:

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。但是我很难对每组记录进行排序。

任何想法?

4

2 回答 2

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;

这应该和现在一样简单和快速。如果你有正确的索引,这应该会飞

我使用usr而不是user,因为后者是标准 SQL 中的保留字。

  • 在子查询u中,获取至少有一行的所有用户type = 'DDD'

  • 将此集合加入基表,获取具有不同事件 ( type <> 'DDD) 的同一用户的所有行。

  • 在该HAVING子句中,排除包含 latestcreation_date和 latest的行的情况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
  • 此查询假定同一用户不能同时有多个事件。否则不靠谱。

-> SQLfiddle显示两者

于 2013-03-22T22:16:30.990 回答
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')

在此处查看小提琴。

于 2013-03-22T22:38:56.477 回答