【问题标题】:MySQL count rows in a joint tableMySQL计算联合表中的行数
【发布时间】:2017-07-13 13:55:16
【问题描述】:

我想计算行数,或者在这种情况下计算同一类别中的产品数量,如果该类别中没有产品,则返回零。

我的查询中的表如下所示:

category                    category_lang                 media
------------                -------------                 ---------
category_id | published     category_id | name | alias    media_id | category_id
-----------------------     --------------------------    ----------------------
1            | 1            1           | One  | one      1        | 1
2            | 1            2           | Two  | two      2        | 2
3            | 1            3           | Three| three    3        | 3

media_lang                          product_category
-------------------------------     ----------------
media_id | url      | file_name     product_id | category_id
-------------------------------     ------------------------
1        | /images/ | file1.jpg     1          | 1
2        | /images/ | file2.jpg     2          | 1
3        | /images/ | file3.jpg     3          | 2

我想要这样的结果:

category_id | category_name | alias | media_id | url      | file_name | count
1           | One           | one   | 1        | /images/ | file1.jpg | 2
2           | Two           | two   | 2        | /images/ | file2.jpg | 1
3           | Three         | three | 3        | /images/ | file3.jpg | 0

我的查询目前看起来像这样

SELECT 
c.`category_id`, 
ca.`name`, 
ca.`alias`, 
m.`media_id`, 
ma.`url`, 
ma.`file_name`,
COUNT(p.`product_id`) AS `count`
FROM `category` c
LEFT JOIN `category_lang` ca ON (c.`category_id` = ca.`category_id`)
LEFT JOIN `media` m ON (c.`category_id` = m.`category_id`)
LEFT JOIN `media_lang` ma ON (m.`media_id` = ma.`media_id`)
LEFT JOIN `product_category` p ON (c.`category_id` = p.`category_id`)
WHERE c.`published` = 1
ORDER BY ca.`name`

我的逻辑显然是错误的,因为这个查询会返回这个:

category_id | category_name | alias | media_id | url      | file_name | count
1           | One           | one   | 1        | /images/ | file1.jpg | 3

我怎样才能达到预期的效果?

【问题讨论】:

  • change COUNT(p.product_id) AS count to COUNT(distinct p.product_id) AS count 问题是您的计数被每个类别有多个记录的联接人为夸大了。
  • 对于我的一生,我不明白你是如何得到这些计数的。据我所知,所有计数都应该是 1,结果集中应该只有 3 条记录减去甚至添加 COUNT()。顺便说一句,您应该使用 GROUP BYCOUNT,但您的预期输出对我来说没有意义。
  • @Tim Biegeleisen 再看一遍。第一类有 2 个产品,第二类有 1 个,第三类有 0 个,
  • @LaciK 我现在看到了,感谢您指出这一点:-)

标签: mysql join count left-join


【解决方案1】:

我认为解决这个问题的最轻松(和理智)的方法是在单独的子查询中汇总 product_category 表中每个类别的产品计数,然后将其加入您已有的:

SELECT 
    c.category_id, 
    ca.name, 
    ca.alias, 
    m.media_id, 
    ma.url, 
    ma.file_name,
    COALESCE(t.cat_count, 0) AS cat_count
FROM category c
LEFT JOIN category_lang ca
    ON c.category_id = ca.category_id
LEFT JOIN media m
    ON c.category_id = m.category_id
LEFT JOIN media_lang ma
    ON m.media_id = ma.media_id
LEFT JOIN
(
    SELECT category_id, COUNT(*) AS cat_count
    FROM product_category
    GROUP BY category_id
) t
    ON c.category_id = t.category_id
WHERE c.published = 1
ORDER BY ca.name

请注意,您的product_category 表没有任何没有产品的类别条目。这不是问题,因为在LEFT JOIN 中,我们可以简单地将NULL 计数视为零。如果给定类别与子查询中的任何内容都不匹配,则会出现 NULL 值。

【讨论】:

  • 谢谢。这是一个很好的解决方案,并且有效。查看您的第一条评论,我认为您已经发布了解决方案 :) 将 GROUP BY c.category_id 添加到我的原始查询中会得到与您相同的结果。你的回答是一个很好的教学例子。
  • @LaciK 小心:只需将GROUP BY c.category_id 添加到您的原始查询中就会给您无效的 SQL,它甚至无法在 MySQL 的某些配置上运行(而且根本不会在 SQL Server、Oracle 等上运行。 )。一般情况下,你不能只是这样聚合。
【解决方案2】:

在我看来,这是您进行计数的地方,并且您确实有进行计数的标准。在类别表中添加产品类别 id 等于类别 id 的额外条件应该可以修复不正确的计数。

SELECT 
c.`category_id`, 
ca.`name`, 
ca.`alias`, 
m.`media_id`, 
ma.`url`, 
ma.`file_name`,
COUNT(p.`product_id`) AS `count`
FROM `category` c
LEFT JOIN `category_lang` ca ON (c.`category_id` = ca.`category_id`)
LEFT JOIN `media` m ON (c.`category_id` = m.`category_id`)
LEFT JOIN `media_lang` ma ON (m.`media_id` = ma.`media_id`)
LEFT JOIN `product_category` p ON (c.`category_id` = p.`category_id`)
WHERE (c.`published` = 1) and (c.`category_id` = p.`category_id`)
ORDER BY ca.`name`

【讨论】:

  • 我可能错了,但对我来说你的语法看起来不对。我在 FROM 之后添加计数会触发语法错误。
  • 你是对的。我把它贴错了地方。 TYVM 捕捉它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-06
  • 2019-12-20
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
相关资源
最近更新 更多