这是表结构
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,然后转到第二个ID,依此类推。我需要在一个查询中,是否可以这样做?
答案 0 :(得分:20)
试试这个:
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 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
现在请注意,BMW
的{{1}} 8 而不是 1 。结果将如下所示:
id
请注意,宝马显示在列表的底部,在其子女之后!这是因为二级排序按Mercedez
E60
Porsche
Cayenne
3 Series
5 Series
BMW
排序,如果父ID恰好高于任何子级,则父级可能不会显示在子级之上。
此查询将解决该问题:
id
http://sqlfiddle.com/#!2/6d6d73/3
要解释此处发生了什么,请先按父行的SELECT
name
FROM
cars
ORDER BY
CASE WHEN parent_id = 0 THEN id ELSE parent_id END, -- another way of writing it: ISNULL(NULLIF(parent_id, 0), id)
parent_id,
id
字段和子行id
字段进行排序。如果您按此顺序,所有孩子将与其父母一起分组,整个列表将由父母的parent_id
字段排序。
但是这并没有在家庭中设置排序,因此父母可以在家庭中的任何地方出现(父母可以出现在顶部,或者可以在中间,或者可能是最后)。
这是其他两个排序字段的来源。第二个字段按id
排序,父行的parent_id
字段始终为parent_id
。安全地假设您的ID字段始终为正,这意味着父记录将始终显示在系列中的顶部。其余的孩子将0
具有相同的值,因此第三个排序字段按其parent_id
字段对家庭中的孩子进行排序。这也可以更改为id
,具体取决于您希望孩子排序的方式。