167

IN() 句の値の順序で並べ替える方法 (おそらくもっと良い方法) があるかどうか疑問に思っています。

問題は、2 つのクエリがあることです。1 つはすべての ID を取得し、もう 1 つはすべての情報を取得します。1 つ目は、2 つ目の順序で並べたい ID の順序を作成します。ID は正しい順序で IN() 句に入れられます。

したがって、次のようになります(非常に単純化されています):

SELECT id FROM table1 WHERE ... ORDER BY display_order, name

SELECT name, description, ... WHERE id IN ([id's from first])

問題は、2 番目のクエリが、ID が IN() 句に入れられた順序と同じ順序で結果を返さないことです。

私が見つけた 1 つの解決策は、すべての ID を自動インクリメント フィールドを持つ一時テーブルに配置し、それを 2 番目のクエリに結合することです。

より良いオプションはありますか?

注:最初のクエリは「ユーザーによって」実行され、2 番目のクエリはバックグラウンド プロセスで実行されるため、サブクエリを使用して 2 つを 1 つのクエリに結合する方法はありません。

私はMySQLを使用していますが、他のDBにもどのようなオプションがあるかを記載しておくと便利かもしれないと考えています.

4

13 に答える 13

203

MySQL のFIELD()関数を使用します。

SELECT name, description, ...
FROM ...
WHERE id IN([ids, any order])
ORDER BY FIELD(id, [ids in order])

FIELD()最初のパラメーター (最初のパラメーター自体を除く) と等しい最初のパラメーターのインデックスを返します。

FIELD('a', 'a', 'b', 'c')

1を返します

FIELD('a', 'c', 'b', 'a')

3を返します

IN()ID を句とFIELD()関数に同じ順序で貼り付けると、これはまさにあなたが望むことを行います。

于 2008-12-28T22:25:38.367 に答える
15

ソートされたデータを取得する方法については、次を参照してください。

SELECT ...
  FROM ...
 WHERE zip IN (91709,92886,92807,...,91356)
   AND user.status=1
ORDER 
    BY provider.package_id DESC 
     , FIELD(zip,91709,92886,92807,...,91356)
LIMIT 10
于 2011-12-01T09:31:06.603 に答える
11

頭に浮かぶ2つのソリューション:

  1. order by case id when 123 then 1 when 456 then 2 else null end asc

  2. order by instr(','||id||',',',123,456,') asc

instr()オラクルからのものです。おそらくあなたはlocate()またはcharindex()そのようなものを持っています)

于 2008-12-28T23:19:39.117 に答える
10

MS SQL Server 2008+でクエリによって入力された値を使用してクエリで任意の並べ替えを実行する場合は、その場でテーブルを作成し、そのように結合することで実行できます (OP の命名法を使用)。

SELECT table1.name, table1.description ... 
FROM (VALUES (id1,1), (id2,2), (id3,3) ...) AS orderTbl(orderKey, orderIdx) 
LEFT JOIN table1 ON orderTbl.orderKey=table1.id
ORDER BY orderTbl.orderIdx

VALUES ステートメントを、ANSI SQL で同じことを行う別のものに置き換えると、これはどの SQL データベースでも機能するはずです。

注: 作成されたテーブル (orderTbl.orderIdx) の 2 番目の列は、100 程度を超えるレコード セットを照会する場合に必要です。もともと orderIdx 列はありませんでしたが、結果セットが 100 を超える場合は、その列で明示的に並べ替える必要があることがわかりました。とにかくSQL Server Express 2014で。

于 2015-12-07T15:42:04.057 に答える
6
SELECT ORDER_NO, DELIVERY_ADDRESS 
from IFSAPP.PURCHASE_ORDER_TAB 
where ORDER_NO in ('52000077','52000079','52000167','52000297','52000204','52000409','52000126') 
ORDER BY instr('52000077,52000079,52000167,52000297,52000204,52000409,52000126',ORDER_NO)

本当によく効きました

于 2012-07-05T08:56:14.097 に答える
6

ソートされたデータを取得するためのAns。

SELECT ...
FROM ...
ORDER  BY FIELD(user_id,5,3,2,...,50)  LIMIT 10
于 2014-01-30T08:38:33.540 に答える
4

IN 句は値のセットを記述し、セットには順序がありません。

結合を使用して列を並べ替えるdisplay_orderソリューションは、最も正しいソリューションです。それ以外は、おそらく DBMS 固有のハックです (または、標準 SQL の OLAP 関数を使って何らかの処理を行っています)。確かに、結合は最も移植性の高いソリューションです (ただし、display_order値を使用してデータを生成することには問題がある場合があります)。順序列を選択する必要がある場合があることに注意してください。これは標準 SQL の要件でしたが、少し前 (おそらく SQL-92 と同じくらい前) に規則として緩和されたと思います。

于 2008-12-29T07:02:59.417 に答える
3

MySQL FIND_IN_SET関数を使用します。

  SELECT * 
    FROM table_name 
   WHERE id IN (..,..,..,..) 
ORDER BY FIND_IN_SET (coloumn_name, .., .., ..);
于 2011-11-24T07:10:15.323 に答える
2

Oracle の場合、instr() 関数を使用した John のソリューションが機能します。これは、機能したわずかに異なるソリューションです- SELECT id FROM table1 WHERE id IN (1, 20, 45, 60) ORDER BY instr('1, 20, 45, 60', id)

于 2012-05-31T23:54:19.700 に答える
1

最初は単一のクエリを作成することを考えていましたが、1 つはユーザーによって実行され、もう 1 つはバックグラウンドで実行されるため、それは不可能だとおっしゃいました。ユーザーからバックグラウンド プロセスに渡す ID のリストをどのように保存していますか? 順序を示す列を持つ一時テーブルにそれらを入れてみませんか。

では、これはどうですか:

  1. ユーザー インターフェイス ビットが実行され、作成した新しいテーブルに値が挿入されます。ID、位置、およびある種のジョブ番号識別子を挿入します)
  2. ジョブ番号がバックグラウンド プロセスに渡されます (すべての ID ではなく)。
  3. バックグラウンド プロセスはステップ 1 でテーブルからの選択を行い、参加して必要な他の情報を取得します。WHERE 句でジョブ番号を使用し、位置列で並べ替えます。
  4. バックグラウンド プロセスは、終了すると、ジョブ識別子に基づいてテーブルから削除します。
于 2008-12-28T23:50:39.787 に答える
0

これを試してみてください:

SELECT name, description, ...
WHERE id IN
    (SELECT id FROM table1 WHERE...)
ORDER BY
    (SELECT display_order FROM table1 WHERE...),
    (SELECT name FROM table1 WHERE...)

相関サブクエリを適切に機能させるには、おそらく WHERE を微調整する必要がありますが、基本原則は正しいはずです。

于 2008-12-28T22:17:27.683 に答える