Answers:
您可以很容易地使用PostgreSQL(在PostgreSQL 8.2中引入)VALUES(),()。
语法如下:
select c.*
from comments c
join (
values
(1,1),
(3,2),
(2,3),
(4,4)
) as x (id, ordering) on c.id = x.id
order by x.ordering
with ordered_products as (select row_number() OVER (ORDER BY whatever) as reportingorder, id from comments) ... ORDER BY reportingorder
。
只是因为它是如此难以找到并且必须传播:在mySQL中,这可以简单得多,但是我不知道它是否可以在其他SQL中工作。
SELECT * FROM `comments`
WHERE `comments`.`id` IN ('12','5','3','17')
ORDER BY FIELD(`comments`.`id`,'12','5','3','17')
ERROR: cannot pass more than 100 arguments to a function
在Postgres 9.4或更高版本中,这可能是最简单,最快的:
SELECT c.*
FROM comments c
JOIN unnest('{1,3,2,4}'::int[]) WITH ORDINALITY t(id, ord) USING (id)
ORDER BY t.ord;
使用新的WITH ORDINALITY
,那@a_horse已经提到。
我们不需要子查询,我们可以像表一样使用set-returning函数。
使用某些字符串而不是ARRAY构造函数传递给数组的字符串文字可能更易于在某些客户端上实现。
详细说明:
我认为这样更好:
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
... order by id=? desc, id=? desc, id=? desc
似乎运行良好:-)
使用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);
IN
列表,这使该问题成为最佳答案……现在只为MySQL找到类似的东西……WHERE
ORDER BY
order by array_position(array[42,48,43], c.id::int);
在某些情况下可能会导致错误。
array_position(array[42, 48, 43]::bigint[], c.id::bigint)
,因此无需截断bigint
为int
。
在Postgres中执行此操作的另一种方法是使用该idx
函数。
SELECT *
FROM comments
ORDER BY idx(array[1,3,2,4], comments.id)
不要忘记先创建idx
函数,如下所述:http : //wiki.postgresql.org/wiki/Array_Index
CREATE EXTENSION intarray;
。
enable_extension
只要您的应用程序用户是该rds_superuser
组的成员,ROR迁移功能就可以使您激活它。
在Postgresql中:
select *
from comments
where id in (1,3,2,4)
order by position(id::text in '1,3,2,4')
position(id::text in '123,345,3,678')
。id 3
将在id之前匹配345
,不是吗?
经过研究,我找到了这个解决方案:
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
但是,这似乎很冗长,并且对于大型数据集可能存在性能问题。谁能评论这些问题?
IN
子句中有数千个值怎么办?因为我必须要做数千条记录。
SELECT * FROM "comments" JOIN (
SELECT 1 as "id",1 as "order" UNION ALL
SELECT 3,2 UNION ALL SELECT 2,3 UNION ALL SELECT 4,4
) j ON "comments"."id" = j."id" ORDER BY j.ORDER
或者,如果您更喜欢邪恶而不是善良:
SELECT * FROM "comments" WHERE ("comments"."id" IN (1,3,2,4))
ORDER BY POSITION(','+"comments"."id"+',' IN ',1,3,2,4,')
这是另一个可行的解决方案,可以使用常量表(http://www.postgresql.org/docs/8.3/interactive/sql-values.html):
SELECT * FROM comments AS c,
(VALUES (1,1),(3,2),(2,3),(4,4) ) AS t (ord_id,ord)
WHERE (c.id IN (1,3,2,4)) AND (c.id = t.ord_id)
ORDER BY ord
但是同样,我不确定这是否表现出色。
我现在有很多答案。我能得到一些投票和评论,以便我知道哪个是赢家!
谢谢大家:-)
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
我认为使用序列的版本略有改进:
CREATE OR REPLACE FUNCTION in_sort(anyarray, out id anyelement, out ordinal int)
LANGUAGE SQL AS
$$
SELECT $1[i], i FROM generate_series(array_lower($1,1),array_upper($1,1)) i;
$$;
SELECT
*
FROM
comments c
INNER JOIN (SELECT * FROM in_sort(ARRAY[1,3,2,4])) AS in_sort
USING (id)
ORDER BY in_sort.ordinal;
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的字段的主表,而ids是存储comments.id的数组。
在PostgreSQL 9.6中传递
让我们对已经说过的内容有一个视觉印象。例如,您有一个包含一些任务的表:
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
您想按其状态对任务列表进行排序。状态是字符串值的列表:
(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