MySQL - 父 + 子类别的总数

Posted

技术标签:

【中文标题】MySQL - 父 + 子类别的总数【英文标题】:MySQL - Total of parent + child categories 【发布时间】:2012-08-04 16:18:16 【问题描述】:

我有两张桌子:

父子“类别”:

id    name         parent_id
1     Food         NULL
2     Pizza        1
3     Pasta        2

“交易”:

id     amount      category_id
1      100         1
2      50          2
3      25          2

我想返回所有类别以及两列:

total = 具有此 category_id 的所有交易的总金额

parentTotal = 总数 + 其所有子类别的总数

示例(使用上表):

id    name         parent_id    total    parentTotal
1     Food         NULL         100      175
2     Pizza        1            0        0
3     Pasta        2            75       0

编辑:

代码已更新(基于下面 Nedret Recep 的代码)并且工作正常...

SELECT 
    tmp1.id, tmp1.name, tmp1.parent_id, tmp1.total, IFNULL(tmp1.total, 0) + IFNULL(tmp2.s, 0)  AS parenttotal
   FROM
        (SELECT
                ca.id, ca.name, ca.parent_id, SUM(tr.amount) as total
        FROM
            categories ca

        LEFT JOIN
                transactions tr
        ON
                tr.category_id = ca.id 
        GROUP BY
                ca.id)
    AS tmp1     

LEFT JOIN 
        (SELECT
            c.id, c.parent_id as categoryid, SUM(t.amount) AS s  
        FROM
            transactions t
        RIGHT JOIN
            categories c
        ON
            t.category_id = c.id
        GROUP BY 
            c.parent_id)
    AS tmp2

ON tmp2.categoryid = tmp1.id 

order by coalesce(tmp1.parent_id, tmp1.id), tmp1.parent_id

非常感谢您的帮助 - 谢谢!

【问题讨论】:

分类是只有两层还是树状结构,深度不限? IE。 Pizza 类别也可以有子类别。仅 2 级和无限级树将有不同的方法。 是的,类别只有两个层次。谢谢 【参考方案1】:

通过一个内连接,我们计算标准类别中的总数。然后使用另一个内部连接,我们计算总和,但这次按 parent_id 分组。然后我们将两个结果表连接起来,将两个总和放在一行中。对于大型表,此查询会很慢,因此应用程序级别的替代方法会做得更好。

  SELECT 
        tmp1.id, tmp1.name, tmp1.parent_id, tmp1.total, tmp1.total + tmp2.s AS parenttotal
   FROM
   (SELECT
        ca.id, ca.name, ca.parent_id, SUM(tr.amount) as total
   FROM
        transactions tr
   INNER JOIN
        categories ca
   ON
        tr.categoru_id = ca.id 
   GROUP BY
        ca.id)AS tmp1     
   LEFT OUTER JOIN 
   (
   SELECT
     c.parent_id as categoryid, SUM(t.amount) AS s  
   FROM
      transactions t
   INNER JOIN
      categories c
   ON
      t.category_id = c.i
   GROUP 
       BY c.id ) AS tmp2
   ON
       tmp2.categoryid = tmp.id 

【讨论】:

谢谢你 - 我用我的代码的更新版本更改了上面的答案 - 基于你的。一切正常。但是,如果父类别没有交易,则总计和父总计都返回零 - 即它不会将子交易的总计相加。知道为什么吗?谢谢 尝试用IFNULL(tmp1.total, 0) + tmp2.s 替换tmp1.total + tmp2.s IFNULL 有助于将NULL 转换为0,否则保留该值。 @ginsberg:其实你可能还需要将IFNULL() 申请到tmp2.s 谢谢你们俩。现在效果很好。以上代码已更新。

以上是关于MySQL - 父 + 子类别的总数的主要内容,如果未能解决你的问题,请参考以下文章

获取包含父/子类别的总行数。困惑为啥 in_array 不起作用

子类将继承父类所有的方法和属性吗?为啥?

Woocommerce 插件 - 子类别的嵌套产品

获取所有属于子类别的文章 多对多 Laravel

JS---子类调用父类的方法

Mysql 子类查询所有父类