[英]How to select more than one row per group in MySQL?
Here is my table "puntos": 这是我的桌子“puntos”:
Equipo Liga Puntos
---------------------------
At. Madrid 1 68
Espanyol 1 64
Barcelona 1 63
Real Madrid 1 61
Castellón 1 48
Murcia 2 78
Elche 2 70
Sevilla 2 60
Valladolid 2 57
I just want to get two rows per different value of the attribute "Liga", the two that have the greatest values of "Puntos" group by "Liga". 我只想获得属性“Liga”的每个不同值的两行,这两个具有“Liga”组的“Puntos”组的最大值。
So it should return something like that: 所以它应该返回类似的东西:
Equipo Liga Puntos
---------------------------
At. Madrid 1 68
Espanyol 1 64
Murcia 2 78
Elche 2 70
I get the result with that query: 我得到了该查询的结果:
SELECT * FROM puntos GROUP BY Liga HAVING max(puntos)
UNION
SELECT p1.Equipo, p1.Liga, max(p1.puntos) FROM puntos p1, (SELECT * FROM puntos GROUP BY Liga HAVING max(puntos) ORDER BY Liga,puntos DESC) p2
WHERE p1.Liga=p2.Liga AND p1.puntos<p2.puntos GROUP BY Liga
ORDER BY Liga,puntos DESC
But that solution that not works if the select values of column "puntos" are equal. 但是,如果列“puntos”的选择值相等,则该解决方案无效。
Is there any other way to do it for any value, equal or not? 有没有其他方法可以为任何价值做,无论是否相等?
First, this solution will only work if Equipo
is unique across all leagues. 首先,只有当
Equipo
在所有联赛中都是独一无二的时候,这个解决方案才有效。 If not - you should add equipoID
and use it instead. 如果不是 - 你应该添加
equipoID
并改为使用它。
Now, we first select the leader of each league. 现在,我们首先选择每个联赛的领导者。 Then create a union with the same select again, only using the WHERE to filter out the teams that we've already got on our first union.
然后再次创建一个具有相同选择的联合,只使用WHERE过滤掉我们在第一个联合上已经获得的团队。 That will essentially give us the follower.
这基本上会给我们追随者。
Here's the query: 这是查询:
SELECT * FROM
(SELECT * FROM puntos ORDER BY `liga`,`puntos` DESC) `leader`
GROUP BY `liga`
UNION
SELECT * FROM
(SELECT * FROM puntos ORDER BY `liga`,`puntos` DESC) `follower`
WHERE `follower`.`equipo` NOT IN
(SELECT equipo FROM
(SELECT * FROM puntos ORDER BY `liga`,`puntos` DESC) `leader`
GROUP BY `liga`
)
GROUP BY `liga`
ORDER BY `liga`
Get the max puntos 获得最大的puntos
SELECT Equipo, Liga, max(Puntos) Puntos FROM results GROUP BY Liga
Then remove the maximum by Liga from the points and get the maximum again 然后从点移除Liga的最大值并再次获得最大值
SELECT Equipo, Liga, max(Puntos) Puntos FROM results A
WHERE Puntos NOT IN
(SELECT max(Puntos) Puntos FROM results B
WHERE A.LIGA = B.LIGA
GROUP BY Liga)
GROUP BY Liga
The wrap the whole select to order the columns 包装整个选择以排序列
SELECT Equipo, Liga, Puntos
FROM
(SELECT Equipo, Liga, max(Puntos) Puntos FROM results GROUP BY Liga
UNION
SELECT Equipo, Liga, max(Puntos) Puntos FROM results A
WHERE Puntos NOT IN
(SELECT max(Puntos) Puntos FROM results B
WHERE A.LIGA = B.LIGA
GROUP BY Liga)
GROUP BY Liga) T
ORDER BY Liga ASC, Puntos DESC
Another option is to use 9.4 User-Defined Variables : 另一种选择是使用9.4用户定义的变量 :
SELECT
`der`.`Equipo`,
`der`.`Liga`,
`der`.`Puntos`
FROM (
SELECT
`p`.`Equipo`,
`p`.`Liga`,
`p`.`Puntos`,
IF(@`prev_liga` != `p`.`Liga`,
@`rownum` := 1,
@`rownum` := @`rownum` + 1
) `rank`,
@`prev_liga` := `p`.`Liga`
FROM (
SELECT
`Equipo`,
`Liga`,
`Puntos`
FROM `puntos`
GROUP BY `Liga`, `Puntos`
ORDER BY `Liga`, `Puntos` DESC
) `p`, (SELECT
@`rownum` := NULL,
@`prev_liga` := 0) `r`
) `der`
WHERE `der`.`rank` <= 2
ORDER BY `der`.`Liga`, `der`.`rank`;
Two teams from the same "Liga" equal "Puntos": 来自同一“Liga”的两支队伍等同于“Puntos”:
SELECT
`der`.`Equipo`,
`der`.`Liga`,
`der`.`Puntos`
FROM (
SELECT
`p`.`Equipo`,
`p`.`Liga`,
`p`.`Puntos`,
IF(@`prev_liga` != `p`.`Liga`,
@`rownum` := 1,
@`rownum` := @`rownum` + 1
) `rank`,
@`prev_liga` := `p`.`Liga`
FROM (
SELECT
`Equipo`,
`Liga`,
`Puntos`
FROM `puntos`
ORDER BY `Liga`, `Puntos` DESC
) `p`, (SELECT
@`rownum` := NULL,
@`prev_liga` := 0) `r`
) `der`
WHERE `der`.`rank` <= 2
ORDER BY `der`.`Liga`, `der`.`rank`;
Hi there I will suggest little different approach to this problem. 嗨,我会建议这个问题的方法很少。
SET @num := 0, @liga := 0;
SELECT Equipo, Liga, Puntos
FROM (SELECT Equipo, Liga, Puntos, @num := if(@liga = Liga, @num + 1, 1) AS rowNumber,
@liga := Liga
FROM (SELECT Equipo, Liga, Puntos
FROM results
ORDER BY Liga, Puntos DESC) t1) tx
WHERE rowNumber <= 2;
Also here is SQL Fiddle to see how it's work... 这里还有SQL小提琴 ,看它是如何工作的...
And here you can take a look at one of my previous (very similar answer)! 在这里你可以看看我以前的一个(非常相似的答案)!
GL! GL!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.