了解SQL查询以查找每个类别嵌套集模型的项目计数

时间:2014-07-16 21:19:13

标签: mysql sql nested-sets

我一直在阅读this并且已经理解了所有查询,直到计算每个类别中的项目。我在这里粘贴了查询和结果。

    SELECT parent.name, COUNT(product.name)
    FROM nested_category AS node ,
            nested_category AS parent,
            product
    WHERE node.lft BETWEEN parent.lft AND parent.rgt
            AND node.category_id = product.category_id
    GROUP BY parent.name
    ORDER BY node.lft;

    +----------------------+---------------------+
    | name                 | COUNT(product.name) |
    +----------------------+---------------------+
    | ELECTRONICS          |                  10 |
    | TELEVISIONS          |                   5 |
    | TUBE                 |                   2 |
    | LCD                  |                   1 |
    | PLASMA               |                   2 |
    | PORTABLE ELECTRONICS |                   5 |
    | MP3 PLAYERS          |                   2 |
    | FLASH                |                   1 |
    | CD PLAYERS           |                   2 |
    | 2 WAY RADIOS         |                   1 |
    +----------------------+---------------------+

究竟发生了什么?有两个名为node和parent的nested_category表副本。在示例的情况下,总共有10个项目,因此有10个节点"从node.category_id = product.category_id开始选择。然后每个节点至少存在一个父节点。但我不理解查询的COUNT(product.name)部分。这如何为您提供每个类别的项目数?我在sql方面不是很熟练。

编辑:我发现此代码存在缺陷。它不会显示零项目的类别。 This seems to fix it,但我也不完全理解。

2 个答案:

答案 0 :(得分:2)

看看GROUP BY条款 - 这解释了计数,我将通过它:

暂时忽略实际的SELECT,FROM子句的第一部分是左手输入nested_category,其别名为' parent'

然后将其作为右手输入加到自身nested_category上,并将其别名为node,但该子句给出右手输入中左手/右手输入左/右值的所有行左/右值:

你最终得到这样的东西(选择所有相关的列):

Parent.Id    Parent.Left  Parent.Right  Node.Left  Node.Right
1             1            10            2          3
1             1            10            4          9
1             1            10            5          6
1             1            10            7          8
2             4            9             5          6
2             4            9             7          8

请注意您多次获取父项(父项*子项数)

这将代表以下层次结构:

  1/10 + 
       |-> 2/3
       |-> 4/9 +
               |-> 5/6
               |-> 7/8

基本上对于左侧输入中的每一行,您都会获得右侧输入中的所有子行

然后分组开始 - 左侧输入的GROUP BY子句组(Parent.Name除非Parent.Name是唯一的,否则可能不是最好的分组!)然后计算右手输入中的行数 - 所以在上面的情况下它会给你

Parent ID 1 (item 1/10) = 4 rows
Parent ID 2 (item 4/9) = 2 rows

当您进行GROUP(或聚合)时,您只能选择出现在GROUP BY子句中的项目,否则您必须使用SUM,COUNT,AVG等聚合函数

编辑:它没有给出任何包含0项的类别的原因是JOIN表示只返回右输入中具有左/右值的行左输入中的行#39;左/右值之间没有任何内容的东西将被连接过滤掉

希望这有助于解释它

答案 1 :(得分:1)

lol @ strawberry的评论

快速回答...你的表nested_category正在自我加入以找出它的'父'。像这样的自联接在数据库中是常见的,其中“父”级别的一个记录将在同一个表中具有它的子记录。在某些设置中,子项将位于不同的表中(查询看起来相同,除了它将引用不同的表而不是我们在此处的相同表)。不要害怕自我加入......把它想象成两个完全独立的表“节点”和“父”。不管怎样,他们有相同的结构和相同的数据,但最好将它们视为单独的表格。

首先,它将所有记录作为“节点”抓取并找到它的父产品(父产品将没有父条目,因此从节点到父母的连接将删除没有关联父记录的父记录...如果这很有意义。)

然后它连接到node.category_id = product.category_id上的product表。这将为每个产品创建一条生产线(5个产品,1个节点将是5个生产线)。

此处的group by语句将获取所有这些行并按父级产品计算它们。一个父母可能有5个节点,每个节点有5个产品......在这种情况下,它会将所有25条记录(5个节点* 5个产品)计入该父记录

当然,具有0个产品的节点被删除:node.category_id = product.category_id ...因此它不会出现在列表中。要显示0个条目,您必须先创建父项列表,然后将其连接到此处的语句...左连接将保留0。