如何使用SQL查询对表记录进行排序,父记录后跟子记录
我有一个表,其中几乎没有记录有一个父记录,如下所示。并非所有这些文件都有父记录如何使用SQL查询对表记录进行排序,父记录后跟子记录,sql,postgresql,hierarchical-data,Sql,Postgresql,Hierarchical Data,我有一个表,其中几乎没有记录有一个父记录,如下所示。并非所有这些文件都有父记录 id | parent_id -------------- 1 | 0 2 | 0 3 | 1 4 | 0 5 | 0 6 | 0 7 | 5 我希望先订购父项,然后订购子项: id | parent_id -------------- 1 | 0 3 | 1 2 | 0 4 | 0 5 | 0 7 | 5 6 | 0 如何在不使用存储过程的情况下使用SQL查询实现这一点 我使用的是
id | parent_id
--------------
1 | 0
2 | 0
3 | 1
4 | 0
5 | 0
6 | 0
7 | 5
我希望先订购父项,然后订购子项:
id | parent_id
--------------
1 | 0
3 | 1
2 | 0
4 | 0
5 | 0
7 | 5
6 | 0
如何在不使用存储过程的情况下使用SQL查询实现这一点
我使用的是postgres。您需要一个在所有级别上都携带根ID的文件,然后您可以根据该文件对行进行排序:
with recursive entries as (
select id, parent_id, id as root_id, 1 as level
from the_table
where parent_id = 0 -- this should be IS NULL
union all
select c.id, c.parent_id, p.root_id, p.level + 1
from the_table c
join entries p on p.id = c.parent_id
)
select id, parent_id
from entries
order by root_id, level, id;
在线示例:我想您需要:
order by coalesce(nullif(parent_id, 0), id), id
基本上,忽略parent_id中的零。然后使用parent_id(如果存在),否则使用id
他是一把小提琴
此版本假定父ID小于子ID,这在数据中是正确的,并且在大多数情况下是有意义的。如果您想明确说明订购情况:
order by coalesce(nullif(parent_id, 0), id),
(parent_id = 0) desc,
id
假设只有一个层次结构,如您的示例所示:
SELECT child.*
FROM tbl AS child
LEFT JOIN tbl AS parent ON parent.id = child.parent_id
ORDER BY COALESCE(parent.id, child.id) -- order by parent if exists
, parent.id IS NOT NULL -- parent first per group
, child.id; -- order rest by id
只有当我们按一些附加属性(如名称)排序时才需要连接,这是典型的情况,因为代理项ID的值没有意义。虽然像您演示的那样只按ID排序,但我们不需要连接,因为所有信息都已经存在,就像Gordon演示的那样。然后我们可以简化:
SELECT *
FROM tbl
ORDER BY CASE WHEN parent_id = 0 THEN id ELSE parent_id END
, parent_id <> 0
, id;
需要按项排序的第二个顺序将父项排序在其子项之前。因为假在真之前排序。见:
仅当可以有多个子项时,才需要最后一个按项目排序的订单。
dbfiddle-使用扩展测试用例来演示项目顺序的相关性。我使用这种方式来进行Postgres:
SELECT id, parent_id, name
FROM my_table
ORDER BY
COALESCE(parent_id,id)||id::varchar
不相关,但是:存储0而不是null来表示没有父对象是个坏主意。这会阻止您使用正确的外键约束。您的示例正好建议1级层次结构。是这样吗?这并没有给我想要的结果,我想在我的原始版本中发布的一个question@m.beginner:联机示例将准确返回问题中列出的结果。这将首先生成父id为0的所有记录,然后打印具有正确父id和子链接的记录。我不想再次转储父id为0的所有记录:这将准确返回您在问题中显示为所需输出的内容。如果这不是您想要的,您需要更新您的问题以显示您真正想要的。这似乎只实现了parent后跟child,因为OP的测试用例构造得很糟糕,总是parent.id