Mode calculation without a subquery field in MySQL?

吃可爱长大的小学妹 提交于 2019-12-10 15:41:56

问题


In my application, each product group has many products, and each product has one manufacturer. These relations are stored by MySQL in InnoDB tables product_groups with an id field, and products with id, product_group and manufacturer fields.

Is there a way to find the most common manufacturer in each product group, without resorting to selecting subqueries?

This is how I'm doing it currently:

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;

回答1:


Try this solution:

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

Explanation:

This still uses a form of subquery, but one which executes only once as opposed to one that executes on a row-by-row basis such as in your original example.

It works by first selecting the product_group id, the manufacturer, and the count of how many times the manufacturer appears for each particular group.

The FROM sub-select will look something like this after execution (just making up data here):

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

Now that we have the sub-select result, we need to pick out the row that has the maximum in the occurences field for each product group.

In the outer query, we group the subselect once again by the product_group field, but this time, only the product_group field. Now when we do our GROUP BY here, we can use a really compelling function in MySQL called GROUP_CONCAT which we can use to concatenate the manufacturers together and in any order we want.

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

What we are doing here is concatenating the manufacturers together that are grouped together per product_group id, the ORDER BY a.occurrences DESC makes sure that the manufacturer with the most appearances appears first in the concatenated list. Finally we are separating each manufacturer with :::. The result of this for product_group 1 will look like:

XYZ:::Test:::Singleton

XYZ appears first since it has the highest value in the occurance field. We only want to select XYZ, so we encase the concatenation within SUBSTRING_INDEX, which will allow us to only pick the first element of the list based on the ::: delimiter.

The end result will be:

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


来源:https://stackoverflow.com/questions/11223003/mode-calculation-without-a-subquery-field-in-mysql

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!