3

此(为简单起见而修改)查询是更大查询的一部分,并与其他选择在日期上连接。但是,我已将此部分固定为狗慢。假设我有一个 UserLoginHistory-table 记录用户的每次登录。对于每个用户,我想要他们首次登录的日期。(稍后在查询中,我按 LogDate 分组以获取每天有多少首次登录。)

select
    LogDate, --(this value is only date, no time)
    UserId
from
    UserLoginHistory ul
where
    not exists
        (
            select 
                * 
            from 
                UserLoginHistory ulPrevious
            where
                ulPrevious.LogDate < ul.LogDate
                and ul.UserId = ulPrevious.UserId
        )
group by ul.LogDate, ul.UserId

显然 NOT EXISTS 部分是慢的。但我不知道如何用更有效的方法来代替它。

使用较小的 UserLogHistory-count,性能没有问题。当我达到 15 000 左右时,它开始变慢。也许我应该将每天的结果批处理到另一个表中,但我想为这个查询找到一个更好的解决方案,因为应该有一个......

谢谢你的时间!

4

2 回答 2

4

您可以使用行编号方法:

select LogDate,UserId from (
    select
       LogDate, 
       UserId
       row_number() over (partition by UserId order by LogDate) as rown
    from
        UserLoginHistory ul
)
where rown = 1

每个 ID 的行由 LogDate 编号,因此最早的将始终编号为 1。

注意:我认为group by原始查询中的 没有必要——该not exists子句应保证您只能获得 UserId 和 LogDate 的唯一组合。

于 2013-03-07T15:53:52.360 回答
4

如果这些是您唯一感兴趣的 2 个字段,您可以不使用简单的聚合吗?

SELECT  LogDate = MIN(LogDate),
        UserID
FROM    UserLoginHistory
GROUP BY UserID;
于 2013-03-07T16:03:11.000 回答