Mysql 选择分组子句中计数的最大值
我有以下表格:Mysql 选择分组子句中计数的最大值,mysql,subquery,mysql-5.7,Mysql,Subquery,Mysql 5.7,我有以下表格: Vehicles(v͟i͟n͟, model,category) Sales(s͟a͟l͟e͟I͟D͟, staffID,customerID,date) vehicleSold(saleID,v͟i͟n͟,salePrice) 当我使用以下方法连接这些表时: select YEAR(Sales.saleDate) , Vehicles.model , count(Vehicles.model) 'Sold' , Vehicles.category
Vehicles(v͟i͟n͟, model,category)
Sales(s͟a͟l͟e͟I͟D͟, staffID,customerID,date)
vehicleSold(saleID,v͟i͟n͟,salePrice)
当我使用以下方法连接这些表时:
select YEAR(Sales.saleDate)
, Vehicles.model
, count(Vehicles.model) 'Sold'
, Vehicles.category
from Vehicles
JOIN vehicleSold
on Vehicles.vin = vehicleSold.vin
JOIN Sales
on Sales.saleID = vehicleSold.saleID
group
by YEAR(Sales.saleDate)
, Vehicles.model
, Vehicles.category;
结果是:
+----------------------+-------------+------+----------------+
| YEAR(Sales.saleDate) | model | Sold | category |
+----------------------+-------------+------+----------------+
| 2020 | Altima | 1 | car |
| 2020 | Flying Spur | 2 | car |
| 2020 | Lifan E3 | 3 | Electric Moped |
| 2020 | Ridgeline | 2 | truck |
| 2020 | Shiver | 4 | motorbike |
+----------------------+-------------+------+----------------+
从这张表中,我想得到一个类别中最畅销的型号。所以,在这种情况下,我只想返回2020年,飞马,汽车作为唯一的一排类别的汽车,因为它是最畅销的2020年在其类别。我尝试使用子查询is MAX(COUNT(*),但我猜mysql中不支持这种情况。如果有人能指出我的错误,并知道如何做到这一点,那将是巨大的帮助 假设您使用支持
row\u number()
或rank()
的MySQL版本8或更高版本,您可以使用这些窗口函数之一
如果每个类别只能有一行,请使用row_number()
,或者如果您想包括排名靠前的任何型号,请像这样使用rank()
select Yr
, model
, Sold
, ctegory
from (
select YEAR(Sales.saleDate) Yr
, Vehicles.model
, count(Vehicles.model) 'Sold'
, Vehicles.category
, ROW_NUMBER() OVER(PARTITION BY YEAR(Sales.saleDate), category
ORDER BY sold DESC)
as rn
from Vehicles
JOIN vehicleSold
on Vehicles.vin = vehicleSold.vin
JOIN Sales
on Sales.saleID = vehicleSold.saleID
group
by YEAR(Sales.saleDate)
, Vehicles.model
, Vehicles.category
) as d
where rn = 1
对于rank,语法几乎相同:
, RANK() OVER(PARTITION BY YEAR(Sales.saleDate), category
ORDER BY sold DESC)
as rnk
注:
dbfiddle对于8之前的MySQL版本(其中
row_number()
不可用),有一种方法模仿row_number()
,这在实践中是可行的,但被一些人认为是“黑客”
它的工作原理是使用一个子查询,必须使用一个order by
子句,这种排序将允许我们确定何时为数据的每个“分组”分配1。这里我将“组”的年份和类别连接起来,如果连接与前一行相同,则行号递增,如果连接与前一行不同,则行号为1。此逻辑由下面所示的IF()
函数执行
SELECT
yr
, model
, sold
, category
FROM (
SELECT
@row_num :=IF(@prev_value=concat(yr, category),@row_num + 1, 1) AS rn
, yr
, model
, sold
, category
, @prev_value := concat(yr, category)
FROM mytable
CROSS JOIN (SELECT @row_num :=1, @prev_value :='') vars
ORDER BY
yr
, category
, sold DESC
) as d
WHERE rn = 1
再加上一点技巧,我们可以将行数模拟扩展到排名模拟,以便返回最高位置的平局:
SELECT
yr
, model
, sold
, category
FROM (
SELECT
@row_num :=IF(@prev_value=concat(yr, category)
, IF(@sold = sold, @row_num, @row_num + 1)
, 1) AS rnk
, yr
, model
, sold
, category
, @prev_value := concat(yr, category)
, @sold := sold
FROM mytable
CROSS JOIN (SELECT @row_num :=1, @prev_value :='', @sold := 1) vars
ORDER BY
yr
, category
, sold DESC
) as d
WHERE rnk = 1
dbfiddle查看MySQL的哪个版本?版本8或更高版本的功能可以轻松解决此问题,以前的版本需要不同的方法。请始终指定您的dbms版本。如果Altima在2020年也销售了2,会发生什么情况?i、 e.如果一年内销售最多的一行超过一行,会发生什么?很抱歉,我不使用版本8,我使用旧版本进行学习。版本5.7。如果你让我知道如何在这个版本,这将是伟大的!