简体   繁体   English

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

[英]Understanding SQL query for finding item count for each category nested set model

I've been reading this and have understood all the queries until the one for counting items in each category. 我一直在阅读此书,并且已经理解了所有查询,直到对每个类别中的项目进行计数为止。 I have pasted the query and the result here. 我在这里粘贴了查询和结果。

    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 |
    +----------------------+---------------------+

What exactly is going on? 到底是怎么回事? There are two copies of the nested_category table named node and parent. nested_category表的两个副本名为node和parent。 In the case of the example, there are 10 items total so there are 10 "nodes" selected since node.category_id = product.category_id . 在该示例的情况下,总共有10个项目,因此由于node.category_id = product.category_id选择了10个“节点”。 Then there exists at least one parent for each node. 然后,每个节点至少存在一个父节点。 But I do not understand the COUNT(product.name) part of the query. 但是我不理解查询的COUNT(product.name)部分。 How does that give you the item count for each category? 如何为您提供每个类别的商品计数? I'm not very skilled in sql. 我在SQL方面不是很熟练。

EDIT: I have found a flaw in this code. 编辑:我发现此代码中的缺陷。 It will not display categories with zero items. 它不会显示零项的类别。 This seems to fix it , but I do not understand it fully either. 这似乎可以解决问题 ,但我也不完全理解。

Take a look at the GROUP BY clause - this explains the count, I'll run it through: 看一下GROUP BY子句-这说明了计数,我将通过以下步骤进行操作:

Ignoring the actual SELECT for a moment, the first part of the FROM clause is the left hand input nested_category which is aliased as 'parent' 暂时忽略实际的SELECT,FROM子句的第一部分是左侧输入nested_category ,别名为“ parent”

This is then joined onto itself nested_category as the right hand input and aliased as node , but the clause gives all rows from the right hand input that have left/right values between the left hand inputs left/right values: 然后,将其作为右侧输入连接到自身nested_category ,并别名为node ,但该子句提供了来自右侧输入的所有行,这些行在左侧输入的左/右值之间具有左/右值:

You end up with something like this (selecting all the relevant columns): 您最终会得到如下所示(选择所有相关列):

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

Notice how you get the Parent item multiple times (parent * number of children) 注意如何多次获得“父项”(父项*子项数)

This would represent the following hierarchy: 这将代表以下层次结构:

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

Essentially for every row in the left input you get all the child rows in the right input 基本上,对于左侧输入中的每一行,您都会在右侧输入中获得所有子行

The grouping then kicks in - the GROUP BY clause groups by the left hand input ( Parent.Name which is probably not the best thing to group on unless Parent.Name is unique!) and then counts the number of rows in the right hand input - so in the case of the above it would give you 然后分组开始Parent.Name GROUP BY子句按左手输入分组( Parent.Name可能不是最好的分组对象,除非Parent.Name是唯一的!),然后计算右手输入的行数-因此,在上述情况下,它会给您

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

When you GROUP (or aggregate) you can only select items that appear in the GROUP BY clause otherwise you must use an aggregate function such as SUM, COUNT, AVG etc 当您进行GROUP(或汇总)时,您只能选择出现在GROUP BY子句中的项目, 否则必须使用汇总函数,例如SUM,COUNT,AVG等

Edit: The reason it give you none of the categories with 0 items is that the JOIN says 'only return rows from the right input which have left/right values that are between any of the rows in the left input'. 编辑:之所以没有为您提供0项类别,是因为JOIN表示“仅从右侧输入返回行,这些行的左侧/右侧值在左侧输入的任何行之间”。 Anything that has nothing between the left/right values will be filtered out by the join 左/右值之间没有任何值的任何内容将被联接过滤掉

Hope this helps explain it 希望这有助于解释它

lol @strawberry's comment 哈哈@strawberry的评论

Quick answer...your table nested_category is doing a self join to itself to pick out it's 'parent'. 快速解答...您的表nested_category正在对其自身进行自我连接以选择其“父级”。 Self joins like this are semi common in databases where one record at the 'parent' level will have it's child records in the same table. 像这样的自联接在数据库中很常见,在该数据库中,“父”级别的一条记录会将其子记录放在同一表中。 In some setups, the children items will be in a different table (query looks the same, except it will refer to the different table instead of the same table as we have here). 在某些设置中,子项将位于不同的表中(查询看起来是一样的,除了它引用的是不同的表,而不是这里的表)。 Don't be afraid of self joins...think of it as two completely seperate tables "node" and "parent". 不要害怕自我联接……把它想象成两个完全分开的表“节点”和“父”。 Admittadely they have the same structure and same data, but best to think of them as seperate tables. 诚然,它们具有相同的结构和数据,但最好将它们视为单独的表。

So first it's grabbing all records as 'nodes' and finding it's parent product (parent products won't have a parent entry, so the join from nodes to parents drop off parent records that have no associated parent record...if that makes sense). 因此,首先将所有记录作为“节点”,并找到其父产品(父产品将没有父条目,因此从节点到父的联接会删除没有关联父记录的父记录...如果有意义) )。

It then joins to the product table on the node.category_id = product.category_id. 然后,它连接到node.category_id = product.category_id上的产品表。 This will create a line for every product (5 products assoicaited to 1 node will be 5 lines). 这将为每个产品创建一条线(与1个节点关联的5个产品将是5条线)。

The group by statement here takes all those lines and counts them up by the parent level product. 此处的group by语句采用所有这些行,并按父级产品进行累加。 It is possible that one parent has 5 nodes which each have 5 products...in this case, it will count all 25 records (5 nodes * 5 products) to that one parent record 一个父级可能有5个节点,每个节点有5个产品...在这种情况下,它将把所有25条记录(5个节点* 5个产品)计入该父级记录

Of course, a node with 0 products is dropped by this : node.category_id = product.category_id...and as such it won't appear on the list. 当然,带有0个产品的节点将通过以下方式删除:node.category_id = product.category_id ...因此,它不会出现在列表中。 To have 0 entries appear, you must first make a list of parent items and then left join it to your statement here...the left join will preserve the 0's. 要显示0项,您必须首先列出父项列表,然后将其连接到此处的语句中。左联接将保留0。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM