在自引用 table 中排序
Order by in a self-referencing table
假设我有以下 table 数据:
+----+-----------+-----------+---------+
| id | name | parent_id | prev_id |
+----+-----------+-----------+---------+
| 1 | Section 1 | NULL | NULL |
| 2 | Item 1.1 | 1 | NULL |
| 3 | Item 1.2 | 1 | 2 |
| 4 | Item 1.3 | 1 | 3 |
| 5 | Section 2 | NULL | 1 |
| 6 | Item 2.1 | 5 | NULL |
| 7 | Item 2.2 | 5 | 6 |
| 8 | Item 2.3 | 5 | 7 |
| 9 | Item 1.4 | 1 | 4 |
+----+-----------+-----------+---------+
工作原理如下:
parent_id
和 prev_id
都是 id
的外键
parent_id
用于区分节和子节(item)
- 即如果
parent_id
为 NULL,则它是一个部分;否则它是一个项目
prev_id
用于表示最后一节或节中的最后一项
- 即如果该行是一个节,则
prev_id
将指向上一节的行;如果该行是一个项目,则 prev_id
将指向该部分中最后一个项目的行
- 如果
prev_id
为 NULL,则它是第一个部分或部分中的第一个项目
- 如果
parent_id
和prev_id
都为NULL,则为第一节
那么,有没有一种方法可以使用 SQL 来订购它,使其看起来像这样:
+----+-----------+-----------+---------+
| id | name | parent_id | prev_id |
+----+-----------+-----------+---------+
| 1 | Section 1 | NULL | NULL |
| 2 | Item 1.1 | 1 | NULL |
| 3 | Item 1.2 | 1 | 2 |
| 4 | Item 1.3 | 1 | 3 |
| 9 | Item 1.4 | 1 | 4 | <---
| 5 | Section 2 | NULL | 1 |
| 6 | Item 2.1 | 5 | NULL |
| 7 | Item 2.2 | 5 | 6 |
| 8 | Item 2.3 | 5 | 7 |
+----+-----------+-----------+---------+
我想
- 第一部分及其项目显示在顶部
- 对于每个后续部分,显示该部分后跟该部分的项目
编辑: 这是我提出的一个查询:
SELECT id, name, parent_id, prev_id FROM
((
SELECT id, name, parent_id, prev_id, id AS some_id
FROM learning_paths
WHERE parent_id IS NULL
)
UNION ALL
(
SELECT id, name, parent_id, prev_id, parent_id AS some_id
FROM learning_paths
WHERE parent_id IS NOT NULL
)) t
ORDER BY t.some_id, prev_id
此版本有效:
order by coalesce(parentid, id),
(parentid is null) desc,
coalesce(previd, parentid, id),
previd,
id
周围可能有更简单的版本。
Here 是 SQL Fiddle(诚然在 Postgres 中,但这对这个问题应该没有影响)。
假设我有以下 table 数据:
+----+-----------+-----------+---------+
| id | name | parent_id | prev_id |
+----+-----------+-----------+---------+
| 1 | Section 1 | NULL | NULL |
| 2 | Item 1.1 | 1 | NULL |
| 3 | Item 1.2 | 1 | 2 |
| 4 | Item 1.3 | 1 | 3 |
| 5 | Section 2 | NULL | 1 |
| 6 | Item 2.1 | 5 | NULL |
| 7 | Item 2.2 | 5 | 6 |
| 8 | Item 2.3 | 5 | 7 |
| 9 | Item 1.4 | 1 | 4 |
+----+-----------+-----------+---------+
工作原理如下:
parent_id
和prev_id
都是id
的外键
parent_id
用于区分节和子节(item)- 即如果
parent_id
为 NULL,则它是一个部分;否则它是一个项目 prev_id
用于表示最后一节或节中的最后一项- 即如果该行是一个节,则
prev_id
将指向上一节的行;如果该行是一个项目,则prev_id
将指向该部分中最后一个项目的行 - 如果
prev_id
为 NULL,则它是第一个部分或部分中的第一个项目 - 如果
parent_id
和prev_id
都为NULL,则为第一节
那么,有没有一种方法可以使用 SQL 来订购它,使其看起来像这样:
+----+-----------+-----------+---------+
| id | name | parent_id | prev_id |
+----+-----------+-----------+---------+
| 1 | Section 1 | NULL | NULL |
| 2 | Item 1.1 | 1 | NULL |
| 3 | Item 1.2 | 1 | 2 |
| 4 | Item 1.3 | 1 | 3 |
| 9 | Item 1.4 | 1 | 4 | <---
| 5 | Section 2 | NULL | 1 |
| 6 | Item 2.1 | 5 | NULL |
| 7 | Item 2.2 | 5 | 6 |
| 8 | Item 2.3 | 5 | 7 |
+----+-----------+-----------+---------+
我想
- 第一部分及其项目显示在顶部
- 对于每个后续部分,显示该部分后跟该部分的项目
编辑: 这是我提出的一个查询:
SELECT id, name, parent_id, prev_id FROM
((
SELECT id, name, parent_id, prev_id, id AS some_id
FROM learning_paths
WHERE parent_id IS NULL
)
UNION ALL
(
SELECT id, name, parent_id, prev_id, parent_id AS some_id
FROM learning_paths
WHERE parent_id IS NOT NULL
)) t
ORDER BY t.some_id, prev_id
此版本有效:
order by coalesce(parentid, id),
(parentid is null) desc,
coalesce(previd, parentid, id),
previd,
id
周围可能有更简单的版本。
Here 是 SQL Fiddle(诚然在 Postgres 中,但这对这个问题应该没有影响)。