【问题标题】:Mode calculation without a subquery field in MySQL?MySQL中没有子查询字段的模式计算?
【发布时间】:2012-06-28 16:42:03
【问题描述】:

在我的应用程序中,每个产品组都有很多产品,每个产品都有一个制造商。这些关系由 MySQL 存储在带有 id 字段的 InnoDB 表 product_groups 和带有 idproduct_groupmanufacturer 字段的 products 中。

有没有办法找到每个产品组中最常见的制造商,而无需选择子查询?

这就是我目前的做法:

SELECT product_groups.id,
  (
    SELECT manufacturer FROM products
    WHERE product_group = product_groups.id
    GROUP BY manufacturer
    ORDER BY count(*) DESC
    LIMIT 1
  ) manufacturer_mode
FROM product_groups;

【问题讨论】:

    标签: mysql sql subquery mode


    【解决方案1】:

    试试这个解决方案:

    SELECT
        a.product_group,
        SUBSTRING_INDEX(GROUP_CONCAT(a.manufacturer ORDER BY a.occurrences DESC SEPARATOR ':::'), ':::', 1) AS manufacturer_mode
    FROM
        (
            SELECT
                aa.product_group,
                aa.manufacturer,
                COUNT(*) AS occurrences
            FROM
                products aa
            GROUP BY
                aa.product_group,
                aa.manufacturer
        ) a
    GROUP BY
        a.product_group
    

    说明:

    这仍然使用一种形式的子查询,但它只执行一次,而不是像在原始示例中那样逐行执行。

    首先选择product_group id、制造商以及制造商在每个特定组中出现的次数。

    FROM 子选择在执行后将如下所示(这里只是弥补数据):

    product_group   |   manufacturer   |    occurrences
    ---------------------------------------------------
    1               |   XYZ            |    4
    1               |   Test           |    2
    1               |   Singleton      |    1
    2               |   Eloran         |    2
    2               |   XYZ            |    1
    

    现在我们有了子选择结果,我们需要在每个产品组的occurences 字段中挑选出最大值的行。

    在外部查询中,我们再次按 product_group 字段对子选择进行分组,但这一次, product_group 字段。现在,当我们在这里执行 GROUP BY 时,我们可以在 MySQL 中使用一个非常引人注目的函数,称为 GROUP_CONCAT,我们可以使用它以我们想要的任何顺序将制造商连接在一起。

    ...GROUP_CONCAT(a.manufacturer ORDER BY a.occurrences DESC SEPARATOR ':::'...
    

    我们在这里所做的是将按照product_group id 分组在一起的制造商连接在一起,ORDER BY a.occurrences DESC 确保出现最多的制造商出现首先 在串联列表中。最后,我们用::: 分隔每个制造商。 product_group 1 的结果如下:

    XYZ:::Test:::Singleton
    

    XYZ 首先出现,因为它在occurance 字段中具有最高值。我们想选择XYZ,因此我们将串联包含在SUBSTRING_INDEX 中,这将允许我们仅根据::: 分隔符选择列表的第一个元素。

    最终结果将是:

    product_group    |    manufacturer_mode
    ---------------------------------------
    1                |    XYZ
    2                |    Eloran
    

    【讨论】:

    • SUBSTRING_INDEX(GROUP_CONCAT( 真的很丑,但我真的很喜欢它用来回答问题的方式。 +1:p
    • 对了,同一个产品的相等出现的情况不是在这里处理的吗?
    • @OlivierCoilland,问题没有说明如何处理相等的事件。现在如果有的话,它只会选择第一个出现的。也许 OP 想根据一个附加字段对其进行排序,这将只涉及向 GROUP_CONCAT() ORDER BY 添加另一个字段。
    猜你喜欢
    • 1970-01-01
    • 2016-07-13
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 2011-01-27
    相关资源
    最近更新 更多