11

これがテーブル構造です

id   parent_id   name
1    0           BMW
2    0           Mercedez
3    0           Porsche
4    1           3 Series
5    2           E60
6    1           5 Series
7    3           Cayenne

テーブルを次のように表示するにはどうすればよいですか

BMW
3 Series
5 Series
Mercedez
E60
Porsche
Cayenne 

上の表は、昇順の ID に続いてその ID に関連付けられた parent_id を示し、次に 2 番目の ID に進みます。単一のクエリが必要ですが、そのようにすることは可能ですか?

4

1 に答える 1

23

これを試して:

SELECT
  name,
  CASE WHEN parent_id = 0 THEN id ELSE parent_id END AS Sort
FROM
  cars
ORDER BY
  Sort,
  id

http://sqlfiddle.com/#!2/9b05f/3


編集:

この回答が賛成票を獲得し続けていることを考えると、私は質問を再検討し、欠陥を見つけました。何らかの理由で、親の ID が子の ID よりも大きい場合、順序が乱れます。上記のクエリは、親 ID がすべての子よりも小さい数である場合にのみ機能します。

問題を説明するために、テーブルが次のようになっていると想像してください。

id   parent_id   name
8    0           BMW
2    0           Mercedez
3    0           Porsche
4    8           3 Series
5    2           E60
6    8           5 Series
7    3           Cayenne

1ではなく8BMWがあることidに注意してください。結果は次のようになります。

Mercedez
E60
Porsche
Cayenne
3 Series
5 Series
BMW

上で、 BMW が子のにリストの一番下に表示されていることに注意してください。これは、2 番目の並べ替え順序が によるものidであり、親 ID がどの子よりも大きい場合、親が子の上に表示されない可能性があるためです。

このクエリはその問題を解決します。

SELECT
  name
FROM
  cars
ORDER BY
  CASE WHEN parent_id = 0 THEN id ELSE parent_id END, -- another way of writing it: IFNULL(NULLIF(parent_id, 0), id)
  parent_id,
  id

http://sqlfiddle.com/#!2/6d6d73/3

ここで何が起こっているかを説明するために、まず親行のidフィールドと子行のフィールドで並べ替えparent_idます。その順序で並べると、すべての子が親とグループ化され、全体のリストは親のidフィールドで並べられます。

ただし、これはファミリー内の並べ替えを設定しないため、親はファミリー内のどこにでも表示される可能性があります (親が一番上に表示されるか、真ん中に表示されるか、最後に表示される可能性があります)。

そこで、他の 2 つの並べ替えフィールドの出番です。2 番目のフィールドは で並べ替えられparent_id、親行のparent_idフィールドは常に0です。ID フィールドが常に正であると安全に仮定すると、これは、親レコードが常にファミリー内で一番上に表示されることを意味します。残りの子はすべて に対して同じ値を持つparent_idため、3 番目の並べ替えフィールドは、ファミリ内の子をフィールド別に並べ替えますidname子をどのように並べ替えるかによって、これを に変更することもできます。

于 2013-06-17T12:36:44.447 に答える