You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为PostgreSQL的SELECT查询结果生成连续编号索引?

问题原因

你遇到的跳号问题本质是SQL执行顺序导致的:row_number() 这类窗口函数的执行时机早于DISTINCT ON,所以序号是在去重前的临时结果集上计算的,去重后自然会出现断号。

解决方案

你只需要把现有查询(去掉序号列)作为子查询,在外层查询再生成序号即可,修改后的代码如下:

SELECT 
  row_number() over(ORDER BY game_id asc) AS num,
  opponent_name,
  opponent_score,
  player_score,
  result,
  layout,
  date
FROM (
  SELECT DISTINCT ON (games.id)
   (SELECT nickname FROM users INNER JOIN users_games ON users.id = users_games.user_id WHERE id != 'some_user_id' AND game_id = games.id ) AS opponent_name,
   (SELECT score FROM users_games WHERE game_id = games.id and user_id != 'some_user_id') as opponent_score, 
   (SELECT score FROM users_games WHERE game_id = games.id and user_id = 'some_user_id') as player_score,
   (SELECT
    CASE
     WHEN (SELECT score FROM users_games WHERE game_id = games.id and user_id = 'some_user_id') > (SELECT score FROM users_games WHERE game_id = games.id and user_id != 'some_user_id') THEN 'Won'
     WHEN (SELECT score FROM users_games WHERE game_id = games.id and user_id != 'some_user_id') > (SELECT score FROM users_games WHERE game_id = games.id and user_id = 'some_user_id') THEN 'Lost'
     ELSE 'Tie'
     END) as result,
   layouts.name AS layout, 
   date(end_time) AS date,
   games.id as game_id
  FROM
   users_games
  INNER JOIN
   users ON users_games.user_id = users.id
  INNER JOIN
   games ON users_games.game_id = games.id
  INNER JOIN layouts
   ON games.layout_id = layouts.id 
   WHERE games.id IN (SELECT game_id FROM users_games WHERE user_id = 'some_user_id') 
   ORDER BY games.id asc
) t
ORDER BY game_id asc;

可选优化方案

你可以通过聚合逻辑替换大量嵌套子查询,提升查询效率和可读性,同时从根源上避免临时结果集重复的问题,参考写法:

SELECT
  row_number() over(ORDER BY g.id asc) AS num,
  MAX(CASE WHEN ug.user_id != 'some_user_id' THEN u.nickname END) AS opponent_name,
  MAX(CASE WHEN ug.user_id != 'some_user_id' THEN ug.score END) AS opponent_score,
  MAX(CASE WHEN ug.user_id = 'some_user_id' THEN ug.score END) AS player_score,
  CASE
    WHEN MAX(CASE WHEN ug.user_id = 'some_user_id' THEN ug.score END) > MAX(CASE WHEN ug.user_id != 'some_user_id' THEN ug.score END) THEN 'Won'
    WHEN MAX(CASE WHEN ug.user_id = 'some_user_id' THEN ug.score END) < MAX(CASE WHEN ug.user_id != 'some_user_id' THEN ug.score END) THEN 'Lost'
    ELSE 'Tie'
  END AS result,
  l.name AS layout,
  date(g.end_time) AS date
FROM users_games ug
INNER JOIN games g ON ug.game_id = g.id
INNER JOIN users u ON ug.user_id = u.id
INNER JOIN layouts l ON g.layout_id = l.id
WHERE g.id IN (SELECT game_id FROM users_games WHERE user_id = 'some_user_id')
GROUP BY g.id, l.name, g.end_time
ORDER BY g.id asc;

内容的提问来源于stack exchange,提问作者Dylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 06:27:03