如何在MySQL中选择没有子项的所有条目

时间:2016-03-21 16:24:50

标签: mysql join subquery

该表格包含以下列

  • CODE VARCHAR(255) - >类的代码(NOT UNIQUE)(例如test或test2)
  • FULLPATH VARCHAR(255) - >完整路径,包括所有父类代码(UNIQUE)(例如test-test2)
  • NAME VARCHAR(255) - >打印的名称(例如01. Test2)
  • PARENT VARCHAR(255) - >可选的父代码(可以为null)(例如测试)

我现在要达到的目的是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

2 个答案:

答案 0 :(得分: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

此处还有一个sql来计算root的所有子节点(具有null父节点的行),而不必为-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

答案 1 :(得分:0)

好的,这是我的看法:

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)

这似乎是正确的。