我在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)。 如何实现这一目标?
当前回答
在Postgres 9.4中,这可以做得更短一些:
select c.*
from comments c
join (
select *
from unnest(array[43,47,42]) with ordinality
) as x (id, ordering) on c.id = x.id
order by x.ordering;
或者在没有派生表的情况下更加紧凑:
select c.*
from comments c
join unnest(array[43,47,42]) with ordinality as x (id, ordering)
on c.id = x.id
order by x.ordering
无需手动为每个值分配/维护位置。
在Postgres 9.6中,可以使用array_position():
with x (id_list) as (
values (array[42,48,43])
)
select c.*
from comments c, x
where id = any (x.id_list)
order by array_position(x.id_list, c.id);
使用CTE时,值列表只需要指定一次。如果这并不重要,也可以写成:
select c.*
from comments c
where id in (42,48,43)
order by array_position(array[42,48,43], c.id);
其他回答
select * from comments where comments.id in
(select unnest(ids) from bbs where id=19795)
order by array_position((select ids from bbs where id=19795),comments.id)
这里,[bbs]是主表,它有一个名为ids的字段, id是存储注释的数组。id。
在postgresql 9.6中通过
在Postgres 9.4中,这可以做得更短一些:
select c.*
from comments c
join (
select *
from unnest(array[43,47,42]) with ordinality
) as x (id, ordering) on c.id = x.id
order by x.ordering;
或者在没有派生表的情况下更加紧凑:
select c.*
from comments c
join unnest(array[43,47,42]) with ordinality as x (id, ordering)
on c.id = x.id
order by x.ordering
无需手动为每个值分配/维护位置。
在Postgres 9.6中,可以使用array_position():
with x (id_list) as (
values (array[42,48,43])
)
select c.*
from comments c, x
where id = any (x.id_list)
order by array_position(x.id_list, c.id);
使用CTE时,值列表只需要指定一次。如果这并不重要,也可以写成:
select c.*
from comments c
where id in (42,48,43)
order by array_position(array[42,48,43], c.id);
无序列,只适用于8.4:
select * from comments c
join
(
select id, row_number() over() as id_sorter
from (select unnest(ARRAY[1,3,2,4]) as id) as y
) x on x.id = c.id
order by x.id_sorter
我认为这样比较好:
SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4))
ORDER BY id=1 DESC, id=3 DESC, id=2 DESC, id=4 DESC
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