G M*_*ode 4 mysql greatest-n-per-group
当我运行以下查询时,
SELECT engines, manufacturer, model, MAX(seats)
FROM planes
GROUP BY engines;
Run Code Online (Sandbox Code Playgroud)
我得到了正确的引擎和座椅结果,但不是正确的制造商、型号组合。此外,我需要的座位数有多个具有相同最大值的行,但引擎/座位只得到一个结果。我已经查看了其他 Stack Exchange 帖子和其他地方,但似乎找不到解决查询的好方法。有什么建议吗?
您的问题似乎是“每组最大的 N”问题。您可以做的是获得每个引擎结果的最大座位数:
SELECT
engines,
MAX(seats) AS max_seats
FROM
planes
GROUP BY
engines
Run Code Online (Sandbox Code Playgroud)
并将它们用作派生表,将它们连接回源以获得与最大值匹配的行:
SELECT
p.engines,
p.manufacturer,
p.model,
es.max_seats
FROM
planes AS p
INNER JOIN
(
SELECT
engines,
MAX(seats) AS max_seats
FROM
planes
GROUP BY
engines
) AS es
ON p.engines = es.engines
AND p.seats = es.max_seats
;
Run Code Online (Sandbox Code Playgroud)
问题是选择中的列比分组依据中的列多。MySQL 中的默认设置允许这样做,但可能会导致不确定的结果。例子:
engines, manufacturer, model, seats
A A A 10
A B C 20
Run Code Online (Sandbox Code Playgroud)
您的查询:
SELECT engines, manufacturer, model, MAX(seats)
FROM planes
GROUP BY engines;
Run Code Online (Sandbox Code Playgroud)
那么意味着,“获取发动机‘A’的最大座位数,并随机选择‘A’的制造商/型号。这可能意味着:
+---------+--------------+-------+------------+
| engines | manufacturer | model | MAX(seats) |
+---------+--------------+-------+------------+
| A | A | B | 20 |
+---------+--------------+-------+------------+
Run Code Online (Sandbox Code Playgroud)
但也可能是:
+---------+--------------+-------+------------+
| engines | manufacturer | model | MAX(seats) |
+---------+--------------+-------+------------+
| A | B | C | 20 |
+---------+--------------+-------+------------+
Run Code Online (Sandbox Code Playgroud)
您可以通过要求完整的组来防止这种情况:
MariaDB [test]> set @@sql_mode = 'ONLY_FULL_GROUP_BY'
-> ;
Query OK, 0 rows affected (0,01 sec)
MariaDB [test]> SELECT engines, manufacturer, model, MAX(seats) FROM planes GROUP BY engines;
ERROR 1055 (42000): 'test.planes.manufacturer' isn't in GROUP BY
Run Code Online (Sandbox Code Playgroud)
如果您想要拥有最多座位的发动机的制造商/型号,您可以首先获取发动机的最大座位,然后加入原始表,如 @Andriy M 答案:
SELECT A.engines, B.manufacturer, B.model, A.seats
from (
SELECT engines, MAX(seats) as seats
FROM planes
GROUP BY engines
) as A
join planes B
on A.engines = B.engines
and A.seats = B.seats;
+---------+--------------+-------+-------+
| engines | manufacturer | model | seats |
+---------+--------------+-------+-------+
| A | B | C | 20 |
+---------+--------------+-------+-------+
Run Code Online (Sandbox Code Playgroud)
其他 DBMS(例如 PostgreSQL、Oracle、DB2 和 SQL-Server)提供了窗口函数,使这种查询变得更容易:
select engines, manufacturer, model, seats
from (
select engines, manufacturer, model, seats
, row_number() over (partition by engine
order by seats desc) as rn
from planes
) where rn = 1;
Run Code Online (Sandbox Code Playgroud)