这条查询原来一个 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:
@@ -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_idx,173ms → 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}`))
|
||||
|
||||
Reference in New Issue
Block a user