MYSQL 通过在逗号分隔的字符串中查找其 ID 来查询以计算项目的后代

MYSQL query to count descendants of items by finding its id in a comma separated string

我的 MYSQL 数据库使用 tree-like 系统,其中每个项目都可以有任意数量的后代。每个项目都有一个包含其 parent 的常规 INT 'parent' 列以及一个 VARCHAR 'parents' 列,该列由包含其所有祖先 ID 的 comma-separated 字符串组成。

id    parent    parents
-------------------------------
1     0         0
2     1         0,1
3     1         0,1
4     3         0,1,3

我需要获取所有项目的列表,每个项目都计算了它们的后代总数。这是我到目前为止的查询:

SELECT items.id AS item_id, 
COUNT(children.id) AS children 
FROM items items 
LEFT JOIN items children ON (items.id IN (children.parents))

这只会发回一行,child 计数为 0。我该如何正确执行此操作?

编辑:

修复查询后,它看起来像这样:

SELECT 
  i.id AS item_id, 
  COUNT(*) AS children 
FROM 
  items i 
LEFT JOIN 
  items c 
  ON (i.id IN (c.parents))
GROUP BY i.id;

结果显示行,但每行只有一个 child。这不反映数据,大概是 IN 语句有问题(FIND_IN_SET 做同样的事情)。

编辑 2:

IN语句改成如下后

ON LOCATE(i.id, c.parents) > 0

项目 1 的 children (3) 数正确,但其余项目均显示为 1 child。第 2 项和第 4 项应为 0,第 3 项应为 1。

您需要 GROUP BY items.id 才能 COUNT() 正常工作。

将别名更改为更明确的名称:

SELECT 
  i.id AS item_id, 
  COUNT(*) AS children 
FROM 
  items i 
LEFT JOIN 
  items c 
  ON FIND_IN_SET(i.id, c.parents) > 0 
WHERE c.id <> i.id
GROUP BY i.id;

有关更复杂的 COUNT()/GROUP BY 示例,请参阅 this question or MySQL documentation. For FIND_IN_SET(), nice example here

参见 sqlfiddle here