【问题标题】:Counting quantity of children with recursion用递归计算孩子的数量
【发布时间】:2020-06-30 05:06:19
【问题描述】:

我有如下图所示的表格。类别具有按 parent_id 的层次结构树。 CategoryProducts 在 Category 和 Product 之间建立了多对多的关系。一种产品可以属于不同的类别。例如“红球”可以放在“运动”和“运动”-s 子类别“足球”中。

如何使用子类别的产品数量计算每个类别中的产品数量?重复无关紧要,例如,类别“运动”可以包含两个“红球”(一个来自自己的类别,一个来自子类别“足球”)。

表关系:

结果表:

这是无法正常工作的 sql 脚本:

    with recursive category_tree as (
    select c.id , c.name , c.parent_id , count(cp.id) as amo
    from temp_category_2 c
    join temp_category_products cp on cp.category_id = c.id
    where c.parent_id = null
    group by c.id
    
    union 
    
    select c2.id , c2.name , c2.parent_id , (select count(cp.id) from temp_category_products cp where cp.category_id = c2.id) as amo
    from temp_category_2 c2 
    join category_tree ct on ct.id = c2.parent_id 
)
select cat.id , cat.parent_id, 
count(cp.id) + coalesce((
    select sum(ct.amo)
    from category_tree ct 
    where ct.parent_id = cat.id
    group by ct.parent_id),0)as amount
from temp_category_2 cat
join temp_category_products cp on cp.category_id = cat.id
group by cat.id , cat.parent_id
;

表格类别:

  id |   name   | parent_id | product_quantity
----+----------+-----------+------------------
  2 | a        |         1 |                3
  3 | s        |         1 |                3
  4 | d        |         2 |                3
  5 | f        |         2 |                4
  6 | g        |         3 |                2
  1 | main     |           |                0
(6 rows)

表产品:

 id |  name
----+---------
  1 | example
  2 | example
  3 | example
  ...
(15 rows)

表 category_products:

 id | category_id | product_id
----+-------------+------------
  1 |           6 |          1
  2 |           6 |          2
  3 |           5 |          3
  4 |           5 |          4
  5 |           5 |          5
  6 |           5 |          6
  7 |           4 |          7
  8 |           4 |          8
  9 |           4 |          9
 10 |           3 |         10
 11 |           3 |         11
 12 |           3 |         12
 13 |           2 |         13
 14 |           2 |         14
 15 |           2 |         15
(15 rows)

我的查询结果(不正确的结果):

 id | parent_id | amount
----+-----------+--------
  3 |         1 |      3
  5 |         2 |      4
  4 |         2 |      3
  6 |         3 |      2
  2 |         1 |      3
(5 rows)

正确的结果应该是:

id | parent_id | amount
----+-----------+--------
  1 |           |      15
  2 |         1 |      10
  3 |         1 |      5
  4 |         2 |      3
  5 |         2 |      4
  6 |         3 |      2
(6 rows)

【问题讨论】:

  • 我觉得你的问题很清楚,但它包含图像,某些用户很难看到。您能否以文本形式提供一个小样本数据,并显示您的查询从样本数据中找到了什么,以及它假设要找到什么?
  • @Scratte 我已经编辑了我的帖子。你能再检查一遍吗?
  • SQL 非常有帮助,谢谢 :) 我认为您的表应该显示为 ascii 表。同样的问题是很多用户将无法看到图像。我认为,如果您要给出无法正常工作的查询结果,它也会变得更容易。请注意,所有重要信息都应以文本形式提供。图像应该只是一个额外的可视化,这对你的表关系的前两个图像很好。您可以使用 this tool 创建 ascii 表 :)

标签: sql postgresql recursion common-table-expression


【解决方案1】:

经过一番努力,我找到了答案。 this blog 上显示了一个类似的示例。

正确的 sql 是:

with recursive  cte(CategoryId, ParentCategoryId, c)
        AS (SELECT  c1.id,
                    c1.parent_id ,
                    (SELECT COUNT(*)
                     FROM   (SELECT DISTINCT
                                    product_id 
                             FROM   temp_category_products AS tcp
                             WHERE  tcp.category_id = c1.id
                            ) AS t1
                    ) AS c
            FROM    temp_category AS c1
            UNION ALL
            SELECT  c2.id,
                    c2.parent_id ,
                    d.c
            FROM    temp_category c2
                    INNER JOIN cte d ON c2.id = d.ParentCategoryId
           )
  SELECT  cte.CategoryId,
          cte.ParentCategoryId,
          SUM(c) AS ProductCount
  FROM    cte
  GROUP BY cte.CategoryId,
          cte.ParentCategoryId;

【讨论】:

    猜你喜欢
    • 2012-08-30
    • 1970-01-01
    • 1970-01-01
    • 2018-01-27
    • 2023-01-20
    • 2016-10-21
    • 1970-01-01
    • 2017-07-01
    • 2014-06-18
    相关资源
    最近更新 更多