【问题标题】:How can I select all entries without a child in MySQL如何在 MySQL 中选择没有孩子的所有条目
【发布时间】:2016-03-21 16:24:49
【问题描述】:

表格有以下列

  • CODE VARCHAR(255) -> 类的代码(不是唯一的)(例如 test 或 test2)
  • FULLPATH VARCHAR(255) -> 包含所有父类代码的完整路径(唯一)(例如 test-test2)
  • NAME VARCHAR(255) -> 打印的名称(例如 01.Test2)
  • PARENT VARCHAR(255) -> 可选父代码(可以为空)(例如测试)

我现在想要达到的是SELECT所有没有孩子的孩子的数量(所以在一棵树上的叶子)

我已经找到了SELECT 来获取所有孩子

SELECT a.*, (COUNT(c.CODE)-1) as 'ChildCount'
FROM dir_asset_class AS a 
LEFT JOIN dir_asset_class AS c ON LOCATE(a.CODE, c.FULLPATH) > 0
WHERE a.PARENT IS NULL 
GROUP BY a.CODE
ORDER BY a.NAME ASC

这将返回没有最高父级的所有子级。

我现在尝试使用如下所示的子选择来获取所有没有子级的子级:

SELECT dac.CODE, dac.FULLPATH
FROM dir_asset_class as dac2 
LEFT JOIN dir_asset_class as dac on locate(dac.CODE, dac2.FULLPATH) > 0 
GROUP BY dac.CODE
HAVING (COUNT(dac.FULLPATH)-1) = 0

它工作了一半......它给了我一些没有其他孩子的孩子。但是很多东西都不见了。

有没有办法在没有过程的情况下解决这个问题(所以只有子选择?)

如果需要更多信息,请告诉我。

编辑:链接到 SQLFiddle:http://sqlfiddle.com/#!9/cd8ff

【问题讨论】:

  • 你能创建一个有足够数据的 sqlfiddle 来测试我们自己吗?
  • 添加了指向 sqlfiddle 的链接。我想我发现了问题可能出在哪里。由于 CODE 不是唯一的,可以多次使用,并且我按 CODE 对其进行分组,因此具有相同 CODE 的多行不在最终结果中。

标签: mysql join subquery


【解决方案1】:

试试这个sqlfiddle

-- get all children that have no child, bottommost children
SELECT c1.*
FROM dir_asset_class as c1
LEFT JOIN dir_asset_class as c2
 ON c1.code != c2.code
   AND (   c2.FULLPATH like CONCAT(c1.code,'-%')
        OR c2.FULLPATH like CONCAT('%-',c1.code,'-%')
        OR c2.FULLPATH like CONCAT('%-',c1.code)
        )
WHERE c2.code IS NULL

这里也是获取 root 的所有子项(父项为 null 的行)的计数的 sql,而不必 -1

-- get count of all children including grandchild of codes that have no parent
SELECT a.*,COUNT(c.CODE) as 'ChildCount'
FROM dir_asset_class as a 
INNER JOIN dir_asset_class as c -- ON LOCATE(a.CODE, c.FULLPATH) > 0
ON c.FULLPATH like CONCAT(a.CODE,'-%')
WHERE a.PARENT IS NULL
AND a.code != c.code
GROUP BY a.CODE
ORDER BY a.NAME ASC;

更新:如果 FULLPATH 是唯一的并且 PARENT 引用它..我们可以使用 this sqlfiddle

SELECT c1.*
FROM dir_asset_class as c1
LEFT JOIN dir_asset_class as c2 ON c1.FULLPATH = c2.parent
WHERE c2.code IS NULL
and c1.parent IS NOT NULL

【讨论】:

  • 这看起来已经比我的尝试好多了。但是,一旦我向数据中添加更多“其他”节点,它也会失败,甚至给父节点提供它(link)。第二条sql很有帮助,谢谢,比我的还准确。
  • 如果你想排除父节点,只需添加并且 c1.parent IS NOT NULL... 现在的逻辑只是查看没有子节点的行
  • 我还注意到您添加了其他...这是一个大问题...因为代码应该是唯一的..否则您必须为每一行添加 id ...或要告诉的内容这是独一无二的。
  • 我试过了,“其他”节点的问题仍然存在。看到这个小提琴:sqfiddle FULLPATH 被标记为主键并且必须是唯一的
  • 试试这个,因为你提到 FULLPATH 是独一无二的......我注意到可能是父引用 FULLPATH sqlfiddle.com/#!9/40f514/1
【解决方案2】:

好的,这是我的看法:

SELECT * FROM `dir_asset_class` WHERE `CODE` NOT IN 
   (SELECT  RIGHT(`PARENT`, LOCATE("-", RPAD(REVERSE(`PARENT`), 255, "-")) - 1) 
   FROM `dir_asset_class` WHERE PARENT IS NOT NULL ) ;

这个想法是获取所有没有出现在parent 值中的元素。为此,我们必须提取parent“树”的所有最后一项,这是通过子查询中的棘手事情完成的。我添加了- 和RPAD 以确保parent 字符串中至少有一个-,否则会导致树的顶部出现问题。

返回:

+--------+-------------------------------+------------+------------------------+
| CODE   | FULLPATH                      | NAME       | PARENT                 |
+--------+-------------------------------+------------+------------------------+
| test3  | TEST-test2-test3              | 01. Test3  | TEST-test2             |
| test61 | TEST-test2-test4-test6-test61 | 01. Test61 | TEST-test2-test4-test6 |
| test62 | TEST-test2-test4-test6-test62 | 02. Test62 | TEST-test2-test4-test6 |
| test63 | TEST-test2-test4-test6-test63 | 03. Test63 | TEST-test2-test4-test6 |
| test5  | TEST-test5                    | 02. Test5  | TEST                   |
| other  | TEST-test7-other              | 03. Other  | TEST-test7             |
| test71 | TEST-test7-test71             | 01. Test71 | TEST-test7             |
| test72 | TEST-test7-test72             | 02. Test72 | TEST-test7             |
| other  | Test10-other                  | 01. Other  | Test10                 |
| test9  | test8-test9                   | 01. Test9  | test8                  |
+--------+-------------------------------+------------+------------------------+
10 rows in set (0.00 sec)

这似乎是对的。

【讨论】:

  • 对于这个例子来说它工作得很好,但是不知何故,当我尝试在实时数据上执行它时,仍然有一些节点被遗漏了。
  • 你能告诉我哪些吗?
  • Can't Reconstruct it with the sql fiddle :/ 但是当我尝试使用这个 sql 时,它会在最后留下一些带有 -other 的叶子,并且还会在列表。我目前正在研究它(也是因为我现在需要让有孩子的孩子计数一个孩子)
  • 嗯,好吧。您确定 code 列具有唯一值吗?您是否尝试将其设置为 unique 键? parent 列是由一系列 code 值组成的吗?
  • 没有代码不是唯一的,但 FULLPATH 是。 Parent Column由Parent的FULLPATH制作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多