我使用以下数据结构来表示数据层次结构。
用户表
+----+------+
| id | name |
+----+------+
| 1 | Bob |
| 2 | Sam |
| 3 | Joe |
| 4 | Kirk |
| 5 | Greg |
+----+------+
关系关闭表
+----------+------------+-------+
| ancestor | descendant | depth |
+----------+------------+-------+
| 1 | 1 | 0 |
| 1 | 2 | 1 |
| 1 | 3 | 2 |
| 1 | 4 | 2 |
| 1 | 5 | 3 |
| 2 | 2 | 0 |
| 2 | 3 | 1 |
| 2 | 4 | 1 |
| 2 | 5 | 2 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 4 | 5 | 1 |
| 5 | 5 | 0 |
+----------+------------+-------+
以上数据代表以下(英文 - ese):
我从以下SQL获取给定用户的儿子:
SELECT u.*
FROM closure AS c
INNER JOIN `user` AS u ON (u.id = c.descendant)
WHERE c.ancestor = 1 AND c.depth = 1
这很好用。但是我还想在树下一直返回后代的数量。到目前为止我能想出的最好的是:
SELECT
u.*,
(
SELECT COUNT(id) FROM `user` WHERE id IN (
SELECT descendant FROM closure
WHERE ancestor = c.descendant
)
) AS descendant_count
FROM closure AS c
INNER JOIN `user` AS u ON (u.id = c.descendant)
WHERE c.ancestor = 1 AND c.depth = 1
上述查询的预期输出为:
+----+------+------------------+
| id | name | descendant_count |
+----+------+------------------+
| 2 | Sam | 3 |
+----+------+------------------+
问题(最后)
有没有比我更好的方法来获得总数?所有这些子选择都是粗略的。
更新
我在意识到这一点,我可能已经为这个例子简化了太多的事情。我有两个子选择来计算,因为我实际上有3个表:类别;项目; category_closure。在我的示例数据中,显然不需要双嵌套子选择。在我的实际数据中有。希望这是有道理的。
答案 0 :(得分:3)
您不需要子查询。您可以通过再次连接到闭包表来获取每个子项的后代数,以查找其祖先是相应子项的所有节点。然后使用GROUP BY,这样你就可以得到每个孩子的计数。
SELECT
u.*,
COUNT(*) AS descendant_count
FROM closure AS c
INNER JOIN `user` AS u ON (u.id = c.descendant)
INNER JOIN closure AS d ON (c.descendant = d.ancestor)
WHERE c.ancestor = 1 AND c.depth = 1
GROUP BY c.descendant