【问题标题】:Understanding SQL query for finding item count for each category nested set model了解用于查找每个类别嵌套集模型的项目计数的 SQL 查询
【发布时间】:2014-07-16 21:19:12
【问题描述】:

我一直在阅读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 个项目,因此自 node.category_id = product.category_id 以来选择了 10 个“节点”。那么每个节点至少存在一个父节点。但我不明白查询的COUNT(product.name) 部分。这如何为您提供每个类别的项目数?我对sql不是很熟练。

编辑:我在这段代码中发现了一个缺陷。它不会显示零项目的类别。 This seems to fix it,不过我也不是很懂。

【问题讨论】:

  • 一篇很棒的文章 - 但遗憾的是它使用了 olde worlde 逗号连接语法 :-(
  • 取出GROUP BY 子句并从product.name 中删除COUNT( ) 函数,然后运行未分组的选择以查看在分组/计数之前它是如何将事物连接在一起的。如果它可以帮助您了解正在发生的事情,请向选择添加更多列。

标签: mysql sql nested-sets


【解决方案1】:

看看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 表示“仅从右输入返回行,其左/右值位于任何行之间在左侧输入中'。任何在左/右值之间没有任何内容的东西都将被连接过滤掉

希望这有助于解释它

【讨论】:

  • Ta - 在手机上看起来不同,但这是网络的本质 :) - 无论如何都已修复
  • 对不起,我删除了它假设只是进行编辑。这是原始评论。 “我建议在‘父 ID 1(项目 1/10)= 4 行’和‘父 ID 2(项目 4/9)= 2 行’之间添加两个空格来创建一个换行符。我不能这样做,因为编辑其他帖子至少需要更改 6 个字符。”
  • 哈哈不用担心,也许我们都删除了所有的 cmets 而忘记了整个事情?!
【解决方案2】:

哈哈@草莓的评论

快速回答...您的表格 nested_category 正在对其自身进行自联接以找出它的“父级”。像这样的自联接在数据库中是半常见的,其中“父”级别的一条记录将在同一个表中具有它的子记录。在某些设置中,子项将位于不同的表中(查询看起来相同,只是它将引用不同的表而不是我们这里的同一个表)。不要害怕自我连接......把它想象成两个完全独立的表“节点”和“父”。诚然,它们具有相同的结构和相同的数据,但最好将它们视为单独的表。

所以首先它将所有记录作为“节点”获取并找到它的父产品(父产品不会有父条目,因此从节点到父项的连接会丢弃没有关联父记录的父记录...如果这是有道理的)。

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多