COUNT(table_name.column_name)没有给出准确的计数。我在错误的列上应用GROUP BY吗?

时间:2014-01-14 20:45:15

标签: mysql sql count aggregate-functions product

我运行的数据库结构有点复杂,可跟踪产品。以下是MySQL Workbench生成的图表:

Products Diagram

在这种结构下,我有3种产品可供我添加。所有这三种产品都具有color属性和red选项。 我在这里设置了一个sql小提琴:http://sqlfiddle.com/#!2/68470/4显示我正在运行的查询,试图让opt_count列在attribute列为{{color列的行上说3 1}}和option列为red

几乎所有其他opt_count值也都是错误的,所以我怀疑我要么没有按正确的列进行分组,要么我没有错误地接近整个问题。

如何为每一行显示正确的opt_count

4 个答案:

答案 0 :(得分:1)

看看这是否有帮助

SELECT products.product_name
, products.product_id
, pvc.combination_id
, pvc.combination
, pva.attribute
, pvo.option
, COUNT(pvo.option) as opt_count
FROM (`products`)
JOIN `product_variant_combinations` pvc ON `products`.`product_id` = `pvc`.`product_id`
JOIN `product_variants` pv ON `pv`.`combination_id` = `pvc`.`combination_id`
JOIN `product_variant_ao_relation` pv_ao ON `pv_ao`.`ao_id` = `pv`.`ao_id`
JOIN `product_variant_options` pvo ON `pvo`.`option_id` = `pv_ao`.`option_id`
JOIN `product_variant_attributes` pva ON `pva`.`attribute_id` = `pv_ao`.`attribute_id`
GROUP BY 1

返回:

| PRODUCT_NAME | PRODUCT_ID | COMBINATION_ID |                                        COMBINATION | ATTRIBUTE | OPTION | OPT_COUNT |
|--------------|------------|----------------|----------------------------------------------------|-----------|--------|-----------|
|         Desk |     111025 |              4 |                  {"color":"Red","material":"Wood"} |     color |    red |         4 |
|         Lamp |     111024 |              1 |                                    {"color":"Red"} |     color |    red |         3 |
|      T shirt |     111026 |              6 | {"color":"Red","size":"Small","material":"Cotton"} |     color |    red |        18 |

答案 1 :(得分:1)

正如其他人所说,您的架构是问题,因为您有多对多关系(许多产品可能有很多选项),这使得查询更加困难。

这是一个查询,为您提供所要求的确切输出。它显示每个选项,分配了多少选项的唯一产品(COUNT(distinct product_id)),并提供以逗号分隔的已分配的product_id值列表。

SELECT pvo.option, 
       count(distinct product_id), 
       group_concat(distinct product_id) products
  FROM (`products`)
  JOIN `product_variant_combinations` pvc using(`product_id`)
  JOIN `product_variants` pv using(`combination_id`)
  JOIN `product_variant_ao_relation` pv_ao using(`ao_id`)
  JOIN `product_variant_options` pvo using(`option_id`)
  JOIN `product_variant_attributes` pva using(`attribute_id`)
 group by pvo.option;

这是红色的输出:

red 3 111026,111025,111024

见这里: http://sqlfiddle.com/#!2/68470/133

您询问了如何添加属性:

SELECT pva.attribute, pvo.option, count(distinct product_id), group_concat(product_id)
FROM (`products`)
JOIN `product_variant_combinations` pvc using(`product_id`)
JOIN `product_variants` pv using(`combination_id`)
JOIN `product_variant_ao_relation` pv_ao using(`ao_id`)
JOIN `product_variant_options` pvo using(`option_id`)
JOIN `product_variant_attributes` pva using(`attribute_id`)
group by pva.attribute, option

您必须在SELECT子句中使用GROUP BY每个非聚合表达式。在这种情况下,两个聚合表达式是COUNT和GROUP_CONCAT,因此,您必须GROUP BY pva.attribute,pvo.option

您可能希望在GROUP BY上找到一个很好的SQL教程。

答案 2 :(得分:0)

使用GROUP BY子句时,需要使用聚合函数(例如maxavgsum)调用所有未分组的字段,以告知数据库如何将它们聚合成分组行。

因为您按单个字段分组并且只为另一个字段指定了聚合,所以结果本质上不可靠且“杂乱” - 您实际上是根据找到的行的磁盘存储顺序获得随机结果。

MySQL是唯一一个默认情况下不强制执行此要求的RDBMS(甚至presents it as a feature) - 所有其他常见数据库(如SQL Server,PostgreSQL和Oracle)都会对您编写的查询产生严重错误。严格检查此规则can be enabled if you wish,但这会打破许多错误编写的遗留应用程序。

答案 3 :(得分:0)

在处理MySQL和你的问题之间存在一些关系,但问题实际上源于“组合行”

group-by包含组合行,该行具有连续列表。 Group-by表示数据库引擎将创建数据集,其中每列中的值相同。

您的组合列包含

{ “颜色”: “红”, “材料”: “木”} {“红色”} { “颜色”: “红”, “大小”: “小”, “材料”: “棉花”} { “颜色”: “红”, “大小”: “中”, “材料”: “棉花”} { “颜色”: “红”, “大小”: “大”, “材料”: “棉花”}

这些都是唯一值,因此使opt_count为1。

为了解决这个问题,您需要获得一个基于color = red的opt_count作为派生表,然后将其重新连接到包含您感兴趣的其余数据的表中

我相信这个查询会返回你想要的内容。请注意,由于组合列的非唯一性,您不会为每个产品返回一行。

-- Outer query to return the product/option/attribute information, plus the count from the derived table
SELECT
 products.product_name, products.product_id,
 product_variant_combinations.combination_id, product_variant_combinations.combination, 
 product_variant_attributes.attribute, 
 product_variant_options.option,
 red_products.option_count

FROM product_variant_combinations

INNER JOIN product_variants
  ON product_variant_combinations.combination_id = product_variants.combination_id

INNER JOIN product_variant_ao_relation
  ON product_variants.ao_id = product_variant_ao_relation.ao_id

INNER JOIN product_variant_options
  ON product_variant_ao_relation.option_id = product_variant_options.option_id

INNER JOIN product_variant_attributes
  ON product_variant_ao_relation.attribute_id = product_variant_attributes.attribute_id

INNER JOIN products
  ON product_variant_combinations.product_id = products.product_id

INNER JOIN
(
    -- Inner table to count the distinct products with the color "red"
    SELECT COUNT(DISTINCT product_variant_combinations.product_id) AS option_count,
      product_variant_attributes.attribute_id,
      product_variant_options.option_id
    FROM product_variant_attributes

    INNER JOIN product_variant_ao_relation
      ON product_variant_attributes.attribute_id = product_variant_ao_relation.attribute_id

    INNER JOIN product_variant_options
      ON product_variant_ao_relation.option_id = product_variant_options.option_id

    INNER JOIN product_variants
      ON product_variant_ao_relation.ao_id

    INNER JOIN product_variant_combinations
        ON product_variants.COMBINATION_ID = product_variant_combinations.COMBINATION_ID

    WHERE product_variant_options.option = 'red'
    AND product_variant_attributes.attribute = 'color'

    GROUP BY product_variant_attributes.attribute_id, product_variant_options.option_id
) AS red_products
    ON product_variant_attributes.attribute_id = red_products.attribute_id
    AND product_variant_options.option_id = red_products.option_id