Postgres - 窗口函数排名和计数

Dav*_*veB 8 postgresql window-functions

我有一些表格可以跟踪运动员在赛道上的时间:

竞赛、竞赛用户和竞赛用户会话

我正在构建一个查询,用于提取每个提供的“competition_user”的当前排名和竞争对手总数,我可以得到排名,但是我的计数 (totalUsers) 没有计算竞争中的所有竞争对手,它似乎只是向上计数给提供的用户(例如,与排名相同)

SELECT compUserId, rank, totalUsers 
    FROM (
        SELECT cu.competition_user_id as compUserId, cu.user_id as userId,  
    count(*) OVER w as totalUsers, rank() OVER w as rank 
        FROM competition_users cu 
        LEFT JOIN current_competition_sessions ccs ON cu.competition_user_id = ccs.competition_user_id 
        LEFT JOIN competition_user_sessions cus ON cus.competition_user_session_id = ccs.competition_user_session_id 
        WHERE cu.left_competition = false 
        AND cu.competition_id in (:compIds)
        WINDOW w AS (PARTITION BY cu.competition_id ORDER BY cus.time_in_seconds ASC) 
    ) as sub 
WHERE compUserId in (:compUserIds)
Run Code Online (Sandbox Code Playgroud)

我的理解是默认框架是整个窗口,而这似乎是从框架开始到当前行计数?

Chr*_*ris 15

你出现问题是你申请的同一WINDOW(命名w为您的)COUNT(*)和你的rank()

当您使用WINDOW包含ORDER BY子句的 a ,然后应用某些聚合(例如SUMor )时COUNT,它会在 ordering 中连续应用聚合,这就是为什么您的COUNTandrank()是相同的。

如果您修改您的查询有多个窗口作为

SELECT compUserId, rank, totalUsers 
FROM (
    SELECT cu.competition_user_id as compUserId, cu.user_id as userId,  
    count(*) OVER (PARTITION BY cu.competition_id) as totalUsers, 
    rank() OVER (PARTITION BY cu.competition_id ORDER BY cus.time_in_seconds ASC) as rank 
    FROM competition_users cu 
    LEFT JOIN current_competition_sessions ccs ON cu.competition_user_id = ccs.competition_user_id 
    LEFT JOIN competition_user_sessions cus ON cus.competition_user_session_id = ccs.competition_user_session_id 
    WHERE cu.left_competition = false 
    AND cu.competition_id in (:compIds)
) as sub 
WHERE compUserId in (:compUserIds);
Run Code Online (Sandbox Code Playgroud)

以便您仅将PARTITION BY应用于您的COUNT(*)窗口,并且您的PARTITION BYORDER BY子句都具有rank(),我相信您会得到想要的结果。

参考这个SQL FIDDLE作为参考,我有一个通用id字段,一个com_num字段代表比赛id,一个com_time字段代表比赛时间。

  • 也许提到 *window frame*,并引用 [the docs](https://www.postgresql.org/docs/9.6/static/tutorial-window.html) 中的具体行来澄清这一点?即: _默认情况下,如果提供了 ORDER BY,则框架由从分区开始到当前行的所有行以及根据 ORDER BY 子句等于当前行的任何后续行组成。当省略 ORDER BY 时,默认框架由分区中的所有行组成。_ (2认同)