根据父ID的mysql排序类别

时间:2013-06-17 12:28:36

标签: mysql sql

这是表结构

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,依此类推。我需要在一个查询中,是否可以这样做?

1 个答案:

答案 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,具体取决于您希望孩子排序的方式。