SQL ORDER BY複数の値を特定の順序で?


94

さて、インデックス付きのキーとインデックスなしのフィールドを持つテーブルがあります。特定の値を持つすべてのレコードを検索して行を返す必要があります。複数の値で注文できるかどうか知りたいのですが。

例:

id     x_field
--     -----
123    a
124    a
125    a
126    b
127    f
128    b
129    a
130    x
131    x
132    b
133    p
134    p
135    i

疑似:結果をこのように並べ替えたい where ORDER BY x_field = 'f', 'p', 'i', 'a'

SELECT *
FROM table
WHERE id NOT IN (126)
ORDER BY x_field 'f', 'p', 'i', 'a'

したがって、結果は次のようになります。

id     x_field
--     -----
127    f
133    p
134    p
135    i
123    a
124    a
125    a
129    a

構文は有効ですが、クエリを実行しても、1レコードに制限しても、結果が返されることはありません。これについて別の方法がありますか?

x_fieldをテスト結果と考えて、条件に該当するすべてのレコードを検証する必要があります。失敗した値、渡された値でテスト結果を並べたいと思いました。したがって、最初に失敗した値を検証し、次にORDER BYを使用して渡された値を検証できます。

私ができないこと:

  • 特定のレコード値を返す必要があるため、GROUP BY
  • WHERE x_field IN( 'f'、 'p'、 'i'、 'a')、いくつかの検証テストに1つのクエリを使用しようとしているので、すべての値が必要です。また、x_field値はDESC / ASC順ではありません

この質問を書いた後、私はこれを再考する必要があると思い始めています、LOL!


多分代わりに組合?結果を返す順序で個別のクエリを作成し、それらのクエリを結合しますか?
なくた

回答:


181
...
WHERE
   x_field IN ('f', 'p', 'i', 'a') ...
ORDER BY
   CASE x_field
      WHEN 'f' THEN 1
      WHEN 'p' THEN 2
      WHEN 'i' THEN 3
      WHEN 'a' THEN 4
      ELSE 5 --needed only is no IN clause above. eg when = 'b'
   END, id

29

LEFT JOINを "VALUES( 'f'、1)、( 'p'、2)、( 'a'、3)、( 'i'、4)"と組み合わせて使用​​し、注文の2番目の列を使用できます-式によって。Postgresは、多くの値がある場合、巨大なCASEよりもはるかに高速なハッシュ結合を使用します。また、自動生成の方が簡単です。

この順序付け情報が固定されている場合は、独自のテーブルが必要です。


6
これは最もエレガントなソリューションです。
jnns 2012年

28

試してください:

ORDER BY x_field='F', x_field='P', x_field='A', x_field='I'

あなたは正しい軌道に乗っていましたが、x値をF値のみに置くことにより、他の3つは定数として扱われ、データセット内の何とも比較されませんでした。


Postgresは暗黙のブール値をサポートしますか?もしそうなら、ブール値はどのようにソートされますか?
gbn 2011年

私はこのソリューションが好きでしたが、何も返されませんでした。
Phill Pafford、2011年

@gbn、はい、false <true。私はこれがうまくいくと思っていたでしょう。
Andrew Lazarus

7
はい、Postgresで動作するイベントです。このソリューションでは、結果が逆順にソートされることに注意してください。したがって、フィールドを逆の順序で配置する必要があります:ORDER BY x_field = 'A'、x_field = 'I'、x_field = 'P'、x_field = 'F'、
igo

16

caseスイッチを使用して、コードをソート可能な数値に変換します。

ORDER BY
  case x_field
  when 'f' then 1
  when 'p' then 2
  when 'i' then 3
  when 'a' then 4
  else 5
  end

10

私はこれのためのよりきれいな解決策を見つけました:

ORDER BY array_position(ARRAY['f', 'p', 'i', 'a']::varchar[], x_field)

注:array_positionにはPostgres v9.5以降が必要です。


1
array_position()はPostgres v9.5以降でのみ使用できることに注意してください。
bigsee

おかげで、これはCASEメソッドよりも好まれました。整数でも機能します。array_position(ARRAY[1, 0]::integer[], x_field)
ポールワトソン

7

提案がすべての作業をする必要がありますが、私は別の色の馬を提案するつもりです。の値の数が適切であり、その値がすでにわかっていると仮定して、値としてF、P、A、およびI(および他の可能な値が適用される場合)を使用して列挙型を作成します。列挙型は、そのステートメントが意味する順序でソートされます。また、序数の位置のみが保存されるため、無駄なスペースなしで、意味のある値の名前を使用できます(実際のアプリケーションではおそらくそうであり、機密性のためにマスクしただけです)。CASEORDER BYx_fieldCREATE


1

選択した列または他の式で並べ替えることができます。

次の例は、ケースステートメントの結果で並べ替える方法を示しています。

  SELECT col1
       , col2
    FROM tbl_Bill
   WHERE col1 = 0
ORDER BY -- order by case-statement
    CASE WHEN tbl_Bill.IsGen = 0 THEN 0
         WHEN tbl_Bill.IsGen = 1 THEN 1
         ELSE 2 END

結果は、 "IsGen = 0"行で始まり、 "IsGen = 1"行と他のすべての行が最後に続くリストになります。

最後に注文パラメーターを追加できます。

  SELECT col1
       , col2
    FROM tbl_Bill
   WHERE col1 = 0
ORDER BY -- order by case-statement
    CASE WHEN tbl_Bill.IsGen = 0 THEN 0
         WHEN tbl_Bill.IsGen = 1 THEN 1
         ELSE 2 END,
         col1,
         col2

このコードスニペットは問題を解決する可能性がありますが、なぜまたはどのように質問に答えるかは説明していません。コードの説明を含めてください。これは、投稿の品質を向上させるのに役立ちます。あなたは将来の読者のための質問に答えていることを覚えておいてください、そしてそれらの人々はあなたのコード提案の理由を知らないかもしれません。
Samuel Philipp

0

CASEを使用したORDER BYを初めて使用するユーザーにとって、これは役立つ場合があります

ORDER BY 
    CASE WHEN GRADE = 'A' THEN 0
         WHEN GRADE = 'B' THEN 1
         ELSE 2 END

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.