我几乎完全重写了这个问题,因为我仍然卡住了......寻找一种方法来查看结果表中的数据,而不必使用 php 或其他一些数据解释器/编程来以我希望的方式查看结果。
基本结果表是这样的(如果你愿意,可以把它弄得更乱):
id1 | id2 | name | ord
------------------------------
a1 | null | name1 | 0
a2 | null | name2 | 1
a3 | null | name3 | 2
b1 | a1 | name4 | 0
b2 | b1 | name5 | 0
b3 | a1 | name6 | 1
b4 | a1 | name7 | 2
c1 | a2 | name8 | 0
c2 | a2 | name9 | 1
d1 | a2 | name10 | 2
d2 | a2 | name11 | 3
d3 | a2 | name12 | 4
d4 | a3 | name13 | 0
c3 | d4 | name14 | 0
c4 | c3 | name15 | 1
d5 | b2 | name16 | 0
我要找的结果是这样的:
id1 | id2 | name | ord
-----------------------------
a1 | null | name1 | 0 <--group header, signified by `id2` is null
b1 | a1 | name4 | 0 <--item that's parent to line below
b2 | b1 | name5 | 0 <--item that's parent to line below
d5 | b2 | name16 | 0 <--last child item
b3 | a1 | name6 | 1 <--special case where `ord` takes over
b4 | a1 | name7 | 2 <--`id2` is still the same, so `ord` sort
a2 | null | name2 | 1 <--next group header
c1 | a2 | name8 | 0 <--`id2` is a2, so name2 is parent, `ord` sort
c2 | a2 | name9 | 1 <--same
d1 | a2 | name10 | 2 <--same
d2 | a2 | name11 | 3 <--same
d3 | a2 | name12 | 4 <--same
a3 | null | name3 | 2 <--next group header
d4 | a3 | name13 | 0 <--`id2` is a3, so name3 is parent
c3 | d4 | name14 | 0 <--`id2` is d3, so name13 is parent
c4 | c3 | name15 | 1 <--`id2` is c3, so name14 is parent
文字说明我需要什么
本质上,我需要 id2
成为按 ord
排序的“组 header ”。然后在它们每个下面,我需要以 id2
等于它上面一行的 id1
以及任何时候 id2
的方式对行进行排序> 与它上面一行的 id2
相同,它应该按 ord
排序。
当 id2
与最后一个 id1
匹配的行用完时,应该出现下一个组标题,并且应该从下一个 id2 重新开始排序
匹配新组头的 id1
。
id2
为 null 的任何项目都是组标题,但在这些组中,ord
基于“父”行重新开始。其中一些行也是其他项目的父级,因此排序的复杂性
实际结果表中还有其他列,因此我将其简化为实际进行排序所需的列。
表格数据解释
实际的 id
列是 char(36),name
是 varchar(1024),ord
是 int(11),而表中的其他列运行色域...我还应该提到,这些结果来自 JOIN
,这样做是为了限制找到该数据的主表的结果。
id1
是主键并且是唯一的,与排序顺序无关,除了具有 id2
的所有行等于给定的 id1
组标题应该出现在它下面。
id2
是对“parent line id”的引用,因此它对于组标题为空;它们是最父级的行,并且通过 ord
有自己的排序顺序。
name
实际上是组标题行的项目名称,它们是类别名称。
例如,假设组标题是食物组,而其中的其他条目是食物类型。因此,一个组标题将是“水果”,下一个是“蔬菜”等。它实际上是 A/V 设备,但水果可能更容易理解。
我做了什么
我在这方面的尝试无处不在。我尝试了各种order by
、field()
、if()
,我也考虑过子查询,但我的技能还不够最多我自己解决这个问题。我认为,如果我能指出正确的方向,我就可以结合我所拥有的来获得正确的结果。不幸的是,出于沮丧,我删除了所有半工作代码,但它可能只不过是一个带有非工作 CASE
语句的 ORDER BY
。
要点:
- 当
id2
为 null 时,它是一个组 header ,并且组 header 应按其ord
字段从低到高(0、1、2)排序。 id1
等于另一行的id2
的任何行都是其父行。换句话说,如果发现一行的id2
等于另一行的id1
,则应将其放在下面。- 如果存在多个行,其中
id2
等于id1
,则排序应首先考虑 #2,然后按ord
从低到高排序.
最佳答案
您描述的数据是分层的(id2 指的是“父级”)并且在 MySQL 中(至少 5.7)没有特定的功能,例如递归 CTE 来处理层次结构。有变通办法,在这里,我们似乎知道我们可以为每个(级别 - 1)使用一个左连接的最大级别数(即,对于 4 个级别,添加 3 个左连接)。一旦通过连接建立了层次结构,然后在各个列中使用 COALESCE(),由于左连接,其中许多列现在可以为 NULL,我们可以安排数据以适合所需的排序顺序。 (好吧,“差不多”。如果您将想要的订单与下面查询显示的订单进行比较,就会发现一些细微差别。)
请引用这个SQL Fiddle还有。
CREATE TABLE Table1
(`id1` varchar(2), `id2` varchar(4), `name` varchar(6), `ord` int)
;
INSERT INTO Table1
(`id1`, `id2`, `name`, `ord`)
VALUES
('a1', NULL, 'name1', 0),
('a2', NULL, 'name2', 1),
('a3', NULL, 'name3', 2),
('b1', 'a1', 'name4', 0),
('b2', 'b1', 'name5', 0),
('b3', 'a1', 'name6', 1),
('b4', 'a1', 'name7', 2),
('c1', 'a2', 'name8', 0),
('c2', 'a2', 'name9', 1),
('d1', 'a2', 'name10', 2),
('d2', 'a2', 'name11', 3),
('d3', 'a2', 'name12', 4),
('d4', 'a3', 'name13', 0),
('c3', 'd4', 'name14', 0),
('c4', 'c3', 'name15', 1),
('d5', 'b2', 'name16', 0)
;
查询:
select
coalesce(p1.id1, p2.id1, p3.id1, p4.id1) id1s
, coalesce(p1.id2, p2.id2, p3.id2, p4.id2) id2s
, coalesce(p1.name, p2.name, p3.name, p4.name) names
, coalesce(p1.ord, p2.ord, p3.ord, p4.ord) ords
#, coalesce(p4.id1, p3.id1, p2.id1, p1.id1) ord1
#, coalesce(p4.id2, p3.id2, p2.id2, p1.id2) ord2
#, coalesce(p4.ord, p3.ord, p2.ord, p1.ord) ord3
from table1 p1
left join table1 p2 on p1.id2 = p2.id1
left join table1 p3 on p2.id2 = p3.id1
left join table1 p4 on p3.id2 = p4.id1
order by
coalesce(p4.id1, p3.id1, p2.id1, p1.id1)
, coalesce(p4.id2, p3.id2, p2.id2, p1.id2)
, coalesce(p4.ord, p3.ord, p2.ord, p1.ord)
, id2s
Result :
| id1s | id2s | names | ords |
|------|--------|--------|------|
| a1 | (null) | name1 | 0 |
| b3 | a1 | name6 | 1 |
| b4 | a1 | name7 | 2 |
| b1 | a1 | name4 | 0 |
| b2 | b1 | name5 | 0 |
| d5 | b2 | name16 | 0 |
| a2 | (null) | name2 | 1 |
| d3 | a2 | name12 | 4 |
| c2 | a2 | name9 | 1 |
| d1 | a2 | name10 | 2 |
| d2 | a2 | name11 | 3 |
| c1 | a2 | name8 | 0 |
| a3 | (null) | name3 | 2 |
| d4 | a3 | name13 | 0 |
| c4 | c3 | name15 | 1 |
| c3 | d4 | name14 | 0 |
想要:
# id1 | id2 | name | ord
# -----------------------------
# a1 | null | name1 | 0 <--group header, signified by `id2` is null
# b1 | a1 | name4 | 0 <--item that's parent to line below
# b2 | b1 | name5 | 0 <--item that's parent to line below
# d5 | b2 | name16 | 0 <--last child item
# b3 | a1 | name6 | 1 <--special case where `ord` takes over
# b4 | a1 | name7 | 2 <--`id2` is still the same, so `ord` sort
# a2 | null | name2 | 1 <--next group header
# c1 | a2 | name8 | 0 <--`id2` is a2, so name2 is parent, `ord` sort
# c2 | a2 | name9 | 1 <--same
# d1 | a2 | name10 | 2 <--same
# d2 | a2 | name11 | 3 <--same
# d3 | a2 | name12 | 4 <--same
# a3 | null | name3 | 2 <--next group header
# d4 | a3 | name13 | 0 <--`id2` is a3, so name3 is parent
# c3 | d4 | name14 | 0 <--`id2` is d3, so name13 is parent
# c4 | c3 | name15 | 1 <--`id2` is c3, so name14 is parent
关于mysql - 复杂的 MySQL 排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41620300/