选择包含前后行的行

时间:2016-04-23 08:21:44

标签: sql postgresql

我有一张表格如下:

CREATE TABLE results (
  id uuid primary key UNIQUE,
  score integer NOT NULL
)

我需要选择一个具有特定UUID的记录及其周围的内容(例如,前后5个)按分数排序

SELECT * FROM results
WHERE id = <SOME_UUID>
ORDERED BY score
OFFSET -5 LIMIT 10; -- apparently this is wrong

我怎样才能有效地做到这一点?

2 个答案:

答案 0 :(得分:0)

它不是'有效',但你可以试试这个:

select a.* from (SELECT * FROM results
WHERE id <> <SOME_UUID> and score <= (select score from results WHERE id = <SOME_UUID>)
ORDERED BY score,id desc
LIMIT 5) as a

UNION ALL

SELECT * FROM results
WHERE id = <SOME_UUID>

UNION ALL
select b.* from (SELECT * FROM results
WHERE id <> <SOME_UUID> and score >= (select score from results WHERE id = <SOME_UUID>)
ORDERED BY score, id asc
LIMIT 5) as b

我试过这个SQL-Server,它需要'ALL'来计算。 因此,您可能会获得具有相同分数的记录作为重复记录。为避免这种情况,请再次使用子查询并使用select distinct。

答案 1 :(得分:0)

解决此问题的一种方法是使用窗口函数分配每行的等级,然后找出您感兴趣的等级:

WITH ranked AS (
  SELECT id, score, rank() OVER (ORDER BY score) AS rnk
  FROM results),
this_rank AS (
  SELECT rnk - 5 AS low_rnk FROM ranked
  WHERE id = <some uuid>::uuid)
SELECT id, score
FROM ranked, this_rank
WHERE rnk >= low_rnk
ORDER BY rnk
LIMIT 11;

对于非常低或高的分数,您获得的行数少于11行,而不是NULL秒的行。

SQLFiddle

另一个细节:PRIMARY KEY已经暗示唯一性,因此您不必在表定义中使用UNIQUE子句。