From 10bf6e8fa12751f4479b3c47431a8d0a22b2dc20 Mon Sep 17 00:00:00 2001 From: Akira Date: Sun, 10 Nov 2024 23:01:32 +0900 Subject: [PATCH] Fix ranking on Excel --- docbase/certificate_template.xlsx | Bin 11361 -> 11356 bytes rog/postgres_views.sql | 104 ++++++++++++++++++++++++++++-- 2 files changed, 98 insertions(+), 6 deletions(-) diff --git a/docbase/certificate_template.xlsx b/docbase/certificate_template.xlsx index 1c1caeb8aa62812edbfbe5c2a451c1c6d3731236..c395cb2f4680377cf7f10ad3927c144b406880ea 100644 GIT binary patch delta 4379 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 OOmRLo!U67oyZ!}meLf`s delta 4402 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 z0000000000000J)@G3 ev.end_datetime AND + gi.goaltime <= ev.end_datetime + INTERVAL '15 minutes' THEN '完走(遅刻)' + ELSE '失格' + END as completion_status, + COALESCE(cs.total_points, 0) as raw_points, + COALESCE(cs.normal_points, 0) as normal_points, + COALESCE(cs.bonus_points, 0) as bonus_points, + COALESCE(cs.penalty_points, 0) as original_penalty_points, + -- 遅刻ペナルティの計算(1秒でも遅れたら、その分数に応じて-50点/分) + CASE + WHEN gi.goaltime > ev.end_datetime THEN + (CEIL(EXTRACT(EPOCH FROM (gi.goaltime - ev.end_datetime)) / 60)) * 50 + ELSE 0 + END as late_penalty_points, + gi.goaltime, + ev.end_datetime + FROM + rog_entry e + JOIN rog_newevent2 ev ON e.event_id = ev.id + LEFT JOIN v_checkin_summary cs ON ev.event_name = cs.event_code + AND CAST(e.zekken_number AS TEXT) = cs.zekken_number + LEFT JOIN rog_goalimages gi ON e.owner_id = gi.user_id + AND gi.event_code = ev.event_name + WHERE + e.is_active = true +), +points_calculation AS ( + SELECT + *, + -- 総合ポイントの再計算(遅刻ペナルティを含む) + GREATEST( + raw_points - late_penalty_points, + 0 + ) as total_points + FROM completion_status +), +valid_rankings AS ( + -- 完走者のみを対象とした順位付け + SELECT + *, + DENSE_RANK() OVER ( + PARTITION BY event_id, category_id + ORDER BY + total_points DESC, + CASE + WHEN completion_status = '完走' THEN 1 + WHEN completion_status = '完走(遅刻)' THEN 2 + END, + goaltime + ) as valid_rank + FROM points_calculation + WHERE completion_status IN ('完走', '完走(遅刻)') +) +SELECT + cs.id, + cs.event_id, + cs.category_id, + cs.zekken_number, + cs.raw_points as original_total_points, + cs.normal_points, + cs.bonus_points, + cs.original_penalty_points, + CASE + WHEN cs.completion_status IN ('完走(遅刻)', '失格') AND cs.goaltime IS NOT NULL THEN cs.late_penalty_points + ELSE 0 + END as late_penalty_points, + ROUND(pc.total_points) as total_points, + cs.completion_status, + CASE + WHEN cs.completion_status IN ('完走', '完走(遅刻)') THEN CAST(vr.valid_rank AS TEXT) + WHEN cs.completion_status = '失格' THEN '失格' + WHEN cs.completion_status = '棄権' THEN '棄権' + END as ranking, + COUNT(*) FILTER (WHERE cs.completion_status IN ('完走', '完走(遅刻)')) + OVER (PARTITION BY cs.event_id, cs.category_id) as total_valid_participants +FROM + completion_status cs + JOIN points_calculation pc ON cs.id = pc.id + LEFT JOIN valid_rankings vr ON cs.id = vr.id; + + -- マテリアライズドビューの作成 --- マテリアライズドビューの再作成 CREATE MATERIALIZED VIEW mv_entry_details AS SELECT -- 既存のフィールド @@ -102,7 +194,7 @@ SELECT -- ランキング情報 cr.ranking as category_rank, - cr.total_participants, + cr.total_valid_participants, -- チームメンバー情報(JSON形式で格納) jsonb_agg( @@ -138,7 +230,7 @@ FROM LEFT JOIN v_category_rankings cr ON e.id = cr.id LEFT JOIN rog_member m ON t.id = m.team_id LEFT JOIN rog_goalimages gi ON e.owner_id = gi.user_id - AND gi.event_id = e.event_id -- ゴール情報の結合条件も修正 + AND gi.event_code = ev.event_name -- ゴール情報の結合条件も修正 GROUP BY e.id, e.zekken_number, e.is_active, e."hasParticipated", e."hasGoaled", e.date, @@ -149,13 +241,13 @@ GROUP BY cu.email, cu.firstname, cu.lastname, cu.date_of_birth, cu.female, cs.total_points, cs.normal_points, cs.bonus_points, cs.penalty_points, cs.total_checkins, cs.purchase_count, cs.last_checkin, - cr.ranking, cr.total_participants, + cr.ranking, cr.total_valid_participants, gi.goalimage, gi.goaltime, e.owner_id; -- インデックスの再作成 CREATE UNIQUE INDEX idx_mv_entry_details_event_zekken -ON mv_entry_details(id); +ON mv_entry_details(id, event_name, zekken_number); -- ビューの更新 REFRESH MATERIALIZED VIEW mv_entry_details;