ПОРЯДОК ВЫПОЛНЕНИЯ В списке значений IN - PullRequest
130 голосов
/ 15 мая 2009

У меня есть простой SQL-запрос в PostgreSQL 8.3, который собирает кучу комментариев. Я предоставляю отсортированный список значений для конструкции IN в предложении WHERE:

SELECT * FROM comments WHERE (comments.id IN (1,3,2,4));

Возвращает комментарии в произвольном порядке, который в моем случае имеет идентификаторы типа 1,2,3,4.

Я хочу, чтобы результирующие строки были отсортированы как список в конструкции IN: (1,3,2,4).
Как этого добиться?

Ответы [ 16 ]

1 голос
/ 15 мая 2009
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,')
0 голосов
/ 06 июня 2017
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

0 голосов
/ 05 июня 2009

Небольшое улучшение по сравнению с версией, которая использует последовательность, я думаю:

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;
0 голосов
/ 15 мая 2009

А вот еще одно решение, которое работает и использует таблицу констант (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

Но опять же я не уверен, что это эффективно.

У меня сейчас куча ответов. Могу ли я получить голосование и комментарии, чтобы я знал, кто победит!

Спасибо всем :-)

0 голосов
/ 15 мая 2009
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;

[EDIT]

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
0 голосов
/ 15 мая 2009

Я согласен со всеми другими авторами, которые говорят «не делай этого» или «SQL не годится». Если вы хотите отсортировать по некоторому фасету комментариев, добавьте еще один целочисленный столбец в одну из ваших таблиц, чтобы сохранить критерии сортировки и отсортировать по этому значению. например, "ORDER BY comments.sort DESC" Если вы хотите сортировать их каждый раз в другом порядке, тогда ... SQL в этом случае не подойдет вам.

...