sup*_*nic 7 mysql sql select sql-order-by nested-sets
我有一个MySQL查询,我认为它可以很好地检索每个节点的所有祖先,从顶部节点开始,直到它的直接节点.但是当我在嵌套集中添加第5级时,它就破了.
下面是示例表,查询和SQL Fiddles:
四级嵌套集:
CREATE TABLE Tree
(title varchar(20) PRIMARY KEY,
`tree` int,
`left` int,
`right` int);
INSERT Tree
VALUES
("Food", 1, 1, 18),
('Fruit', 1, 2, 11),
('Red', 1, 3, 6),
('Cherry', 1, 4, 5),
('Yellow', 1, 7, 10),
('Banana', 1, 8, 9),
('Meat', 1, 12, 17),
('Beef', 1, 13, 14),
('Pork', 1, 15, 16);
Run Code Online (Sandbox Code Playgroud)
查询:
SELECT t0.title node
,(SELECT GROUP_CONCAT(t2.title)
FROM Tree t2
WHERE t2.left<t0.left AND t2.right>t0.right
ORDER BY t2.left) ancestors
FROM Tree t0
GROUP BY t0.title;
Run Code Online (Sandbox Code Playgroud)
节点的返回结果Banana是Food,Fruit,Yellow- Perfect.你可以在这里看到SQL Fiddle - 4 Levels
当我在下面的5级表上运行相同的查询时,第5级节点以错误的顺序返回:
CREATE TABLE Tree
(title varchar(20) PRIMARY KEY,
`tree` int,
`left` int,
`right` int);
INSERT Tree
VALUES
("Food", 1, 1, 24),
('Fruit', 1, 2, 13),
('Red', 1, 3, 8),
('Cherry', 1, 4, 7),
('Cherry_pie', 1, 5, 6),
('Yellow', 1, 9, 12),
('Banana', 1, 10, 11),
('Meat', 1, 14, 23),
('Beef', 1, 15, 16),
('Pork', 1, 17, 22),
('Bacon', 1, 18, 21),
('Bacon_Sandwich', 1, 19, 20);
Run Code Online (Sandbox Code Playgroud)
返回的结果为Bacon_Sandwich是Bacon,Food,Meat,Pork这是不正确的顺序应该是Food,Meat,Pork,Bacon-你可以看到这个在这里SQL小提琴- 5档
我不确定发生了什么,因为我不太了解子查询.任何人都可以对此有所了解吗?
调查后编辑:
哇!!看起来写出这一切并阅读订购,GROUP_CONCAT给了我一些灵感.
添加ORDER BY到实际GROUP_CONCAT函数并从子查询的末尾删除解决了该问题.我现在收到Food,Meat,Pork,Bacon节点Bacon_Sandwich
SELECT t0.title node
,(SELECT GROUP_CONCAT(t2.title ORDER BY t2.left)
FROM Tree t2
WHERE t2.left<t0.left AND t2.right>t0.right
) ancestors
FROM Tree t0
GROUP BY t0.title;
Run Code Online (Sandbox Code Playgroud)
我仍然不知道为什么.在ORDER BY子查询结束时工作4级但不是5级?!?!
如果有人可以解释问题是什么以及为什么要ORDER BY修复它,我将非常感激.
如果在不包含GROUP BY子句的语句中使用组函数,则它等效于对所有行进行分组.
为了使这一点更容易理解,我将省略子查询并将问题减少到香蕉.香蕉是集[10,11].正确排序的祖先是:
SELECT "banana" as node, GROUP_CONCAT(title ORDER by `left`)
FROM Tree WHERE `left` < 10 AND `right` > 11
GROUP BY node;
Run Code Online (Sandbox Code Playgroud)
的ORDER BY必须是GROUP_CONCAT()只要你想聚合函数进行排序.ORDER BY外部按汇总结果排序(即结果GROUP_CONCAT()).直到4级工作的事实才是运气.ORDER BY对聚合函数没有影响.无论是否有ORDER BY以下结果,您都会获得相同的结果:
SELECT GROUP_CONCAT(title)
FROM Tree WHERE `left` < 10 AND `right` > 11
/* ORDER BY `left` */
Run Code Online (Sandbox Code Playgroud)
它可能有助于理解
SELECT GROUP_CONCAT(title ORDER BY left) FROM Tree WHERE … ORDER BY left它的作用:
获取一个选择(WHERE),它以未定义的顺序产生三行:
("Food")
("Yellow")
("Fruit")
将结果聚合为一行(隐式GROUP BY)以便能够使用聚合函数:
(("Food","Yellow", "Fruit"))
在其上触发聚合函数(GROUP_CONCAT(title, ORDER BY link)).即按顺序排序然后连接:
("Food,Fruit,Yellow")
现在终于对结果进行了排序(ORDER BY).因为它只有一行,所以排序不会改变.
("Food,Fruit,Yellow")
| 归档时间: |
|
| 查看次数: |
4218 次 |
| 最近记录: |