在我的应用程序中,每个产品组都有许多产品,每个产品都有一个制造商。这些关系由MySQL存储在InnoDB表product_groups
中,id
字段,products
包含id
,product_group
和manufacturer
字段。< / p>
有没有办法在每个产品组中找到最常见的制造商,而无需选择子查询?
这就是我目前正在做的事情:
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;
答案 0 :(得分:5)
试试这个解决方案:
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
确保最具外观的制造商首先出现 连接列表中的em> 。最后,我们将每个制造商与:::
分开。 product_group
1
的结果如下所示:
XYZ:::Test:::Singleton
XYZ
首先出现,因为它在occurance
字段中具有最高值。我们仅想要选择XYZ
,因此我们将SUBSTRING_INDEX
中的连接包含在内,这样我们就只能根据{{1}选择列表的第一个元素分隔符。
最终结果将是:
:::