【问题标题】:inner join and count records recursively递归内连接和计数记录
【发布时间】:2020-04-11 03:08:32
【问题描述】:

我有两个名为 Topics 和 DocumentTopics 的表

主题表具有以下结构

di_name |父主题

Topics 中的记录可以是主主题,也可以是主主题的子主题。如果记录是主主题,则 parentTopic 的值为空。

DocumentsTopics 具有以下结构

doc_name | topic_di_name

documentsTopics 按名称和主题保存我所有文档的记录。我可以使用 topic->di_name 和 documentTopics->topic_di_name

加入两个表
SELECT t1.topic_di_name, count(t1.topic_di_name) as count 
FROM DocumentsTopics t1 
INNER JOIN Topics t2
ON t1.topic_di_name = t2.di_name
GROUP BY t1.topic_di_name;

但我真正想要的是仅按主要主题对主题进行分组,并获得主要主题下所有记录及其所有子主题的总和。这些可能会深入到不止一个级别。

这是一个带有示例数据的架构

有 2 个主要主题,但只有一个有兄弟姐妹。我要查找的总计数仅针对主要主题,但它们应包括其中所有同级主题的计数。

我猜测这样做的唯一方法是运行递归函数,但我不确定如何使用单个 SQL 查询来做到这一点。有可能吗?

任何帮助将不胜感激

【问题讨论】:

  • 样本数据和期望的结果将阐明您想要做什么。
  • 这可以在 MySQL 8.x 中完成。你有 MySQL 5.x 还是 8.x?
  • 正如 Gordon 所说,一些示例数据和预期结果对帮助您至关重要。
  • 我可以得到最新的 MySQL。我有一个新的 UBUNTU 安装,所以假设 MySQL 8.x。我正在努力获取一些示例数据。
  • @JohnyDGood “有 2 个主要主题,但只有一个有兄弟姐妹。”你的意思是只有一个有孩子

标签: mysql sql


【解决方案1】:

这是在子查询中使用UNION 的另一种方法,以防这对任何人都更有意义:

SELECT `der`.`parentTopic`,
  SUM(IF(`dt`.`topic_di_name` = `der`.`subTopic`,1,0)) AS `counter`
FROM (
SELECT `parentTopic`,
  `di_name` AS `subTopic`
FROM `topics` 
WHERE `parentTopic` IS NOT NULL

UNION 

SELECT `di_name` AS `parentTopic`,
  `di_name` AS `subTopic`
FROM `topics`
WHERE `parentTopic` IS NULL) AS `der`
JOIN `documentsTopics` AS `dt` ON `dt`.`topic_di_name` = `der`.`subTopic`
GROUP BY `der`.`parentTopic`
;

Here's this answer in sql fiddle.

希望这会有所帮助!

【讨论】:

  • 不确定 OP 是否关心它是否超过一级子类别,但如果是这样,这不起作用sqlfiddle.com/#!9/bf33be
【解决方案2】:

为什么不能使用:

SELECT t3.parent_key, count(t3.parent_key)
FROM DocumentsTopics t1 
INNER JOIN Topics t2
ON t1.topic_di_name = t2.di_name
LEFT JOIN (select *, coalesce(parentTopic, di_name) parent_key from Topics) t3
ON t2.di_name = t3.di_name
GROUP BY t3.parent_key

【讨论】:

  • 你能在你的 Q 中展示第二层的数据结构是什么样的吗?最多有两个吗?
【解决方案3】:

这样的事情应该适用于两个级别。

https://www.db-fiddle.com/f/vcjUtUfxsn4yaKnQhmQJ6d/5

SELECT IFNULL(t.parentTopic,t.di_name) AS main_topics,COUNT(*) AS counter
FROM DocumentsTopics d 
INNER JOIN Topics t ON d.topic_di_name=t.di_name 
GROUP BY 1

【讨论】:

    【解决方案4】:

    我认为这将在 mySql 8.0 中工作,并为您提供超过一级的嵌套结果,但我无权进行测试

    with recursive cte as (
      SELECT `parentTopic`,
      `di_name` 
    FROM `topics` 
    WHERE `parentTopic` IS NOT NULL
      union all
      select
      `parentTopic`,
      `di_name` 
      from `topics` t2
      inner join cte on t2.`parentTopic` = cte.`di_name`
      )
    
      select * from cte
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-15
      • 1970-01-01
      • 2020-04-16
      • 2015-04-25
      • 1970-01-01
      相关资源
      最近更新 更多