トラックの周りのアスリートの時間を追跡するいくつかのテーブルがあります。
コンテスト、competition_users、competion_user_sessions
提供された「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)
私の理解では、デフォルトのフレームはウィンドウ全体でしたが、これはフレームの開始から現在の行まで数えているようです?
問題は、COUNT(*)
とrank()
の両方に同じWINDOW
(w
という名前)を適用していることです。
ORDER BY
句を含むWINDOW
を使用し、次にSUM
やCOUNT
などの特定の集計を適用すると、 集計は順序全体で継続的に適用されます 、これがCOUNT
とrank()
が同一である理由です。
クエリを変更する場合、複数のウィンドウを
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);
PARTITION BY
をCOUNT(*)
ウィンドウにのみ適用し、PARTITION BY
とORDER BY
の両方の句をrank()
に指定すると、必要な結果が得られると思います。
これを参照として参照してくださいSQL FIDDLE。ここで、汎用のid
フィールド、com_num
フィールドがあります。競技IDを表すにはcom_time
フィールドを使用して、競技者の時間を表します。