fix(题目分析): 「卡住的题」只看公共题,别把比赛题也算进来
Some checks failed
Deploy / deploy (push) Has been cancelled

这条查询原来一个 where 都没有,比赛题一起进榜。隔壁 ac-trend 在同一个文件、同一块
面板,isNull(contestId) 写得明明白白,所以判定是漏写而不是口径选择。

比赛题的题号是每场比赛各自从 1 开始编的(快照里 61 道不同的题都叫「1」、61 道叫
「2」),一旦挤进前 40,那一行显示的题号会指向一道根本不存在的公共题。眼下还没
发生:前 40 的门槛是 97 人卡住,比赛题最多的一道是 59 人 —— 但两个班一起考的场次
有 95 人,撞上一道难题就够得着。

对公共题的数字没有任何影响:比赛提交挂的是比赛自己的 problem 行(快照实测两个方向
的交叉都是 0 条),公共题那一行本来就只统计自己的提交。实跑接口逐行比对,改前改后
前 40 集合完全一致,只有三处并列名次的先后不同 —— 那是这条查询本来就没有确定性
tiebreaker,并列的题在两次刷新之间也会自己换位置。

顺带能用上 0013 的 submission_public_metrics_idx:183ms / 18646 buffers →
80ms / 788。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KqjE6qPo67fqVDKn6Bx7yd
This commit is contained in:
2026-09-08 18:30:05 -06:00
parent 80f3b21e95
commit 6bef55904f

View File

@@ -192,6 +192,19 @@ adminTagRoutes.get("/problem-analytics/stuck", requireTeacher, async (c) => {
failedUsers: sql<number>`count(distinct ${schema.submission.userId}) ${failedFilter}`.mapWith(Number),
}).from(schema.submission)
.innerJoin(schema.problem, eq(schema.submission.problemId, schema.problem.id))
/**
* 只看公共题,和隔壁 ac-trend 同一个口径。原来这里一个 where 都没有,比赛题
* 也进榜 —— 而比赛题的题号是每场比赛各自从 1 开始编的(快照里 61 道不同的题
* 都叫「1」一旦挤进前 40那一行显示的题号会指向一道根本不存在的公共题。
*
* 眼下还没发生:前 40 的门槛是 97 人卡住,比赛题最多的一道是 59 人。但两个班
* 一起考的场次有 95 人,撞上一道难题就够得着了。
*
* 加了这条对公共题的数字**没有任何影响**:比赛提交挂的是比赛自己的 problem 行
* (快照实测两个方向的交叉都是 0 条),公共题那一行本来就只统计自己的提交。
* 顺带让这条查询能用上 0013 的 submission_public_metrics_idx173ms → 82ms。
*/
.where(isNull(schema.submission.contestId))
.groupBy(schema.problem.id, schema.problem.displayId, schema.problem.title)
.having(sql`count(distinct ${schema.submission.userId}) ${failedFilter} > 0`)
.orderBy(desc(sql`count(distinct ${schema.submission.userId}) ${failedFilter}`))