在SQL中有效地查找下一个事件

时间:2011-07-19 20:22:55

标签: sql sql-server-2008

我的问题的基本要点是,对于每个事件A,我需要找到与同一用户相关联的最早的事件B.目前,我有:

SELECT e.UserID, e.date, min(e2.date) 
FROM Event e INNER JOIN 
    Event e2 ON e.UserID = e2.UserID AND e.date <= e2.date
WHERE e.Event LIKE 'A' AND e2.Event LIKE 'B'

但是,对于每个事件A(用户可能发生任意次数),会发生大量事件B,因此内连接会创建大量额外的行,然后必须在min函数上进行清除。有没有更有效/更快的方法呢?

(服务器是MSSQL Server 2008)

更新 Rank()会更快吗?

Select UserID, date, date2 
from (
    Select e.UserID, e.date, e2.date as date2, rank() OVER (PARTITION BY e.date, e.UserID ORDER BY e2.date) as rank
    FROM Event e INNER JOIN Event e2 on e.UserID = e2.UserID
    WHERE e.Event = 'A' and e2.Event = 'B' and e.date <= e2.date
)
WHERE rank = 1

或者优化会使它们基本相同吗?

2 个答案:

答案 0 :(得分:0)

我知道这样做的唯一更快的方法是要求你在循环中处理每个事件A并使用使用TOP和ORDER BY的单独查询找到第一个事件B,这使得它能够以合适的方式查找答案指数。这可以在存储过程中完成,以实现最高效率。

答案 1 :(得分:0)

第三次加入会更快,像这样吗?可能不是,但它可能值得尝试。表“e3”中返回的任何数据表示日期中间日期和e2日期。所以我们离开了,加上NULL值。

SELECT e.UserID, e.date, e2.date 
FROM Event e 
INNER JOIN Event e2 ON (e.UserID = e2.UserID AND e.date <= e2.date)
 LEFT JOIN Event e3 ON (e.UserID = e3.UserID AND e.date <= e3.date AND e3.date <= e2.date AND e3.Event = 'B')
WHERE e.Event = 'A' AND e2.Event = 'B'
AND e3.date IS NULL

我认为这可能与您的MIN查询使用相同的策略,但可能不是?我很想知道两种方式。