我的问题的基本要点是,对于每个事件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
或者优化会使它们基本相同吗?
答案 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
查询使用相同的策略,但可能不是?我很想知道两种方式。