我在PostgreSQL 8.3中有一个简单的SQL查询,它抓取了一堆注释。我在WHERE子句中为IN构造提供了一个排序的值列表:
SELECT * FROM comments WHERE (comments.id IN (1,3,2,4));
这将以任意顺序返回注释,在my中恰好是id,如1,2,3,4。
我希望结果行像in结构中的列表一样排序:(1,3,2,4)。 如何实现这一目标?
我在PostgreSQL 8.3中有一个简单的SQL查询,它抓取了一堆注释。我在WHERE子句中为IN构造提供了一个排序的值列表:
SELECT * FROM comments WHERE (comments.id IN (1,3,2,4));
这将以任意顺序返回注释,在my中恰好是id,如1,2,3,4。
我希望结果行像in结构中的列表一样排序:(1,3,2,4)。 如何实现这一目标?
当前回答
要做到这一点,我认为您可能应该有一个额外的“ORDER”表,它定义了id到ORDER的映射(有效地执行您对自己的问题的回答),然后您可以将其用作选择上的附加列,然后对其进行排序。
通过这种方式,您可以显式地描述您希望在数据库中的顺序,以及它应该在哪里。
其他回答
在Postgres中另一种方法是使用idx函数。
SELECT *
FROM comments
ORDER BY idx(array[1,3,2,4], comments.id)
不要忘记首先创建idx函数,如下所述:http://wiki.postgresql.org/wiki/Array_Index
通过进一步研究,我发现了这个解决方案:
SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4))
ORDER BY CASE "comments"."id"
WHEN 1 THEN 1
WHEN 3 THEN 2
WHEN 2 THEN 3
WHEN 4 THEN 4
END
然而,这似乎相当冗长,并且对于大型数据集可能会有性能问题。 有人能就这些问题发表评论吗?
要做到这一点,我认为您可能应该有一个额外的“ORDER”表,它定义了id到ORDER的映射(有效地执行您对自己的问题的回答),然后您可以将其用作选择上的附加列,然后对其进行排序。
通过这种方式,您可以显式地描述您希望在数据库中的顺序,以及它应该在哪里。
create sequence serial start 1;
select * from comments c
join (select unnest(ARRAY[1,3,2,4]) as id, nextval('serial') as id_sorter) x
on x.id = c.id
order by x.id_sorter;
drop sequence serial;
(编辑)
Unnest在8.3中还没有内置,但你可以自己创建一个(任何的美丽*):
create function unnest(anyarray) returns setof anyelement
language sql as
$$
select $1[i] from generate_series(array_lower($1,1),array_upper($1,1)) i;
$$;
该函数可以在任何类型下工作:
select unnest(array['John','Paul','George','Ringo']) as beatle
select unnest(array[1,3,2,4]) as id
让我们对已经说过的内容有一个直观的印象。例如,你有一个带有一些任务的表:
SELECT a.id,a.status,a.description FROM minicloud_tasks as a ORDER BY random();
id | status | description
----+------------+------------------
4 | processing | work on postgres
6 | deleted | need some rest
3 | pending | garden party
5 | completed | work on html
并且您希望按状态对任务列表进行排序。 status是一个字符串值列表:
(processing, pending, completed, deleted)
诀窍是给每个状态值一个整数,并以数字顺序排列列表:
SELECT a.id,a.status,a.description FROM minicloud_tasks AS a
JOIN (
VALUES ('processing', 1), ('pending', 2), ('completed', 3), ('deleted', 4)
) AS b (status, id) ON (a.status = b.status)
ORDER BY b.id ASC;
这就导致:
id | status | description
----+------------+------------------
4 | processing | work on postgres
3 | pending | garden party
5 | completed | work on html
6 | deleted | need some rest
信贷@user80168