我在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的映射(有效地执行您对自己的问题的回答),然后您可以将其用作选择上的附加列,然后对其进行排序。

通过这种方式,您可以显式地描述您希望在数据库中的顺序,以及它应该在哪里。

其他回答

相比使用序列的版本略有改进,我认为:

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;

我同意其他所有说“不要那样做”或“SQL不擅长那样做”的帖子。如果您想按注释的某个方面排序,那么向其中一个表添加另一个整数列以保存排序条件并按该值排序。按注释排序。“如果你想每次都按不同的顺序排序,那么……在这种情况下,SQL不适合您。

要做到这一点,我认为您可能应该有一个额外的“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

在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 was introduced with in Postgres 9.4. No need for a subquery, we can use the set-returning function like a table directly. (A.k.a. "table-function".) A string literal to hand in the array instead of an ARRAY constructor may be easier to implement with some clients. For convenience (optionally), copy the column name we are joining to ("id" in the example), so we can join with a short USING clause to only get a single instance of the join column in the result. Works with any input type. If your key column is of type text, provide something like '{foo,bar,baz}'::text[].

详细解释:

PostgreSQL unnest()与元素号