【问题标题】:select product count for each category, when products are in sub-categories当产品在子类别中时,为每个类别选择产品数量
【发布时间】:2014-09-27 09:33:32
【问题描述】:

这是产品的表结构

PROD_ID     CATEG_ID
1           2
2           21
3           211
4           5
5           51

这是一个类别的表结构

CATEG_ID    PARENT_CATEG_ID
2           NULL
5           NULL
21          2
211         21
51          5

在为每个类别(包括嵌套类别)选择产品数量时遇到困难。 例如,类别2 有1 个产品,类别21 有1 个产品,类别211 有1 个产品,并且由于类别21221 分别是类别2 的直接/间接祖先,类别2 有3 个产品。所以我需要一个查询或只是一种方法来获得这样的东西:

CATEG_ID    PARENT_CATEG_ID    PRODUCT_COUNT
2           NULL               3   (including product count for categories 21 and 221)
5           NULL               2   (including product count for category 51)
21          2                  2   (including product count for category 221)
211         21                 1   (no category ancestor, only product count for self)
51          5                  1   (no category ancestor, only product count for self) 

是否可以仅使用 SQL 或我需要添加一些 PHP?

【问题讨论】:

  • 类别是否遵循这种很好的模式,即通过删除 id 的最后一位来获得父级?
  • @Gordon Linoff 他们是,但在某种程度上,我不能依赖它
  • 然后测试“a_horse_with_no_name”的答案,如果正确则接受并投票。
  • 自从他发帖我就一直在玩sql。有些事情就是行不通,所以我没有接受。 Ty 无论如何都是为了你的兴趣

标签: sql postgresql recursive-query


【解决方案1】:

以下应该这样做:

with recursive cat as (
  select categ_id, 
         parent_categ_id,
         categ_id as root_category, 
         1 as level
  from categories
  where parent_categ_id is null
  union all
  select c.categ_id,
         c.parent_categ_id,
         p.root_category,
         p.level + 1
  from categories c
    join cat as p on p.categ_id = c.parent_categ_id
)
select c.categ_id, 
       p.prod_id,
       (select count(*) from cat c2 where c2.level >= c.level and c2.root_category = c.root_category) as cnt
from cat c
  left join products p on p.categ_id = c.categ_id
;

递归查询首先构建整个类别树。它返回每个类别的根类别以及该类别在特定根类别的子树内的嵌套级别。 CTE 本身返回:

类别 ID | parent_categ_id |根类别 |等级 ---------+-----------------+----------------+------ 2 | (空) | 2 | 1 21 | 2 | 2 | 2 211 | 21 | 2 | 3 5 | (空) | 5 | 1 51 | 5 | 5 | 2

然后用于连接产品表并对同一根类别中包含的产品进行运行求和(即count(p.prod_id) over (partition by c.root_category order by level desc) 部分)。所以完整查询的结果是这样的:

类别 ID | prod_id | product_count ---------+---------+-------------- 2 | 1 | 3 21 | 2 | 2 211 | 3 | 1 5 | 4 | 2 51 | 5 | 1

SQLFiddle:http://sqlfiddle.com/#!15/d6261/15

【讨论】:

  • 老兄的回答很好!请告诉我,这是想要的行为吗? sqlfiddle.com/#!15/d6261/11 它返回每个产品行中每个根类别的产品计数
  • @IvanHanák:查看我的编辑 - 虽然我认为该解决方案不会表现良好。
  • @a_horse_with_no_name 很抱歉触发了一个旧帖子,但是如果有一个表 category_types ,在这种情况下我们将如何计算产品?
【解决方案2】:

这里我们检查 c1.categ 是否有子类别,递归查询从自身开始,通过在其下构建树来获取所有子类别 ID。如果有,那么它也计算产品在子类别下

select c1.categ_id,c1.parent_categ_id,count(prods.prod_id)
as product_count from categ c1
join prods on prods.categ_id=c1.categ_id or prods.categ_id
in( with recursive tree(id,parent_id)as 
(select categ_id,parent_categ_id from categ 
where categ_id=c1.categ_id  
union all
select cat.categ_id,cat.parent_categ_id from categ cat
join tree on tree.id=cat.parent_categ_id) select id from tree)
group by c1.categ_id,c1.parent_categ_id order by product_count

结果如下

+----------+-----------------+---------------+
| categ_id | parent_categ_id | product_count |
+----------+-----------------+---------------+
|       51 |               5 |             1 |
|      211 |              21 |             1 |
|        5 |            NULL |             2 |
|       21 |               2 |             2 |
|        2 |            NULL |             3 |
+----------+-----------------+---------------+

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多