206

PostgreSQL 8.3 には、多数のコメントを取得する単純な SQL クエリがあります。句の構造に値の並べ替えられたリストを提供します。INWHERE

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

これは、たまたま のような ID である任意の順序でコメントを返します1,2,3,4

結果の行をコンストラクトのリストのように並べ替えたいIN: (1,3,2,4).
それを達成する方法は?

4

17 に答える 17

125

(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
于 2009-05-15T08:32:50.907 に答える
73

見つけるのが非常に難しく、広める必要があるという理由だけで: mySQL ではこれをはるかに簡単に行うことができますが、他の SQL で機能するかどうかはわかりません。

SELECT * FROM `comments`
WHERE `comments`.`id` IN ('12','5','3','17')
ORDER BY FIELD(`comments`.`id`,'12','5','3','17')
于 2012-01-15T21:19:27.730 に答える
50

私はこの方法がより良いと思います:

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
于 2012-02-28T02:51:52.280 に答える
30

Postgres でそれを行う別の方法は、idx関数を使用することです。

SELECT *
FROM comments
ORDER BY idx(array[1,3,2,4], comments.id)

idxここで説明されているように、最初に関数を作成することを忘れないでください: http://wiki.postgresql.org/wiki/Array_Index

于 2013-01-13T14:49:13.020 に答える
27

Postgresql では:

select *
from comments
where id in (1,3,2,4)
order by position(id::text in '1,3,2,4')
于 2013-03-26T11:48:54.753 に答える
2

これをさらに調査すると、この解決策が見つかりました:

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

ただし、これはかなり冗長に見え、大規模なデータセットではパフォーマンスの問題が発生する可能性があります。誰でもこれらの問題についてコメントできますか?

于 2009-05-15T00:22:03.923 に答える
2

これを行うには、注文するIDのマッピングを定義する追加の「ORDER」テーブルがおそらく必要だと思います(あなた自身の質問に対する回答が言ったことを効果的に実行します)。これは、選択した追加の列として使用できますその後、並べ替えることができます。

このようにして、データベース内の必要な順序を明示的に記述します。

于 2009-05-15T00:29:59.320 に答える
2

sans SEQUENCE、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
于 2009-05-15T01:17:37.363 に答える
1
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,')
于 2009-05-15T00:35:21.803 に答える
0
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 is not yet built-in in 8.3, but you can create one yourself(the beauty of any*):

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;
$$;

that function can work in any type:

select unnest(array['John','Paul','George','Ringo']) as beatle
select unnest(array[1,3,2,4]) as id
于 2009-05-15T00:54:16.217 に答える
0

And here's another solution that works and uses a constant table (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

But again I'm not sure that this is performant.

I've got a bunch of answers now. Can I get some voting and comments so I know which is the winner!

Thanks All :-)

于 2009-05-15T00:59:11.167 に答える
0

私が思うシーケンスを使用するバージョンよりもわずかな改善:

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;
于 2009-06-05T15:45:22.643 に答える
0

すでに言われたことについて視覚的な印象を得ましょう。たとえば、いくつかのタスクを含むテーブルがあるとします。

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

于 2019-07-11T21:15:53.200 に答える
-2

「そんなことはしないでください」または「SQL はそれが得意ではありません」と言っている他のすべての投稿者に同意します。コメントのいくつかの面で並べ替えたい場合は、テーブルの 1 つに別の整数列を追加して、並べ替え基準を保持し、その値で並べ替えます。例: "ORDER BY comments.sort DESC " 毎回異なる順序で並べ替えたい場合... この場合、SQL は役に立ちません。

于 2009-05-15T00:31:30.237 に答える