如何在 MySQL 中每组 select 多行?

How to select more than one row per group in MySQL?

这是我的 table "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

我只想为属性 "Liga" 的每个不同值获取两行,具有 "Puntos" 最大值的两行按 "Liga" 分组。

所以它应该 return 类似的东西:

 Equipo      Liga  Puntos
---------------------------
 At. Madrid     1     68
 Espanyol       1     64
 Murcia         2     78
 Elche          2     70

我得到了那个查询的结果:

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

但如果 "puntos" 列的 select 值相等,则该解决方案无效。

对于任何值,是否有任何其他方法可以做到这一点?

首先,此解决方案仅在 Equipo 在所有联赛中都是唯一的情况下才有效。如果不是 - 您应该添加 equipoID 并改为使用它。

现在,我们先select各联赛的领头羊。然后再次创建具有相同 select 的联合,仅使用 WHERE 过滤掉我们在第一个联合中已经拥有的团队。这基本上会给我们带来追随者。

查询如下:

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`

获得最大的 puntos

SELECT Equipo, Liga, max(Puntos) Puntos FROM results GROUP BY 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

将整个 select 换行以对列进行排序

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

检查SqlFiddle

另一种选择是使用 9.4 User-Defined Variables:

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`;

SQL Fiddle demo

来自同一 "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`;

SQL Fiddle demo

你好,我会建议一些不同的方法来解决这个问题。

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;

这里还有 SQL Fiddle 看看它是如何工作的...

还有你可以看看我之前的一篇(非常相似的回答)!

GL!