Heim  >  Fragen und Antworten  >  Hauptteil

Erfassen Sie die ersten n Datensätze in jedem gruppierten Ergebnis

<p>Das Folgende ist das einfachste mögliche Beispiel, aber jede Lösung sollte sich auf die erforderlichen n Top-Ergebnisse skalieren lassen: </p> <p>Wie erhalten Sie anhand der folgenden Tabelle, die Spalten für Personen, Gruppen und Alter enthält, die beiden ältesten Personen in jeder Gruppe? (Gleichstände innerhalb einer Gruppe sollten nicht zu mehr Ergebnissen führen, sondern stattdessen die Top 2 in alphabetischer Reihenfolge ergeben) </p> <vor> +--------+-------+-----+ |. Person |. Gruppe | +--------+-------+-----+ |. Bob |. 1 | |Jill|1|34| |. Shawn |. 1 | |. Jake |. 29 | |. Paul |. 2 | |. Laura |. 2 | +--------+-------+-----+ </pre> <p>Gewünschter Ergebnissatz: </p> <vor> +--------+-------+-----+ |. Shawn |. 1 | |Jill|1|34| |. Laura |. 2 | |. Paul |. 2 | +--------+-------+-----+ </pre> <hr>

Ich habe eine gute MySQL-spezifische Antwort von @Bohemian erhalten: </p> <pre class="brush:php;toolbar:false;">select * from (select * from mytable order by `Group`, Age desc, Person) x gruppieren nach „Gruppe“</pre> <p>Es wäre schön, darauf aufbauen zu können, aber ich weiß nicht, wie. </p>

P粉785957729P粉785957729447 Tage vor427

Antworte allen(2)Ich werde antworten

  • P粉340264283

    P粉3402642832023-08-22 19:25:52

    在其他数据库中,您可以使用ROW_NUMBER来实现此功能。MySQL不支持ROW_NUMBER,但您可以使用变量来模拟它:

    SELECT
        person,
        groupname,
        age
    FROM
    (
        SELECT
            person,
            groupname,
            age,
            @rn := IF(@prev = groupname, @rn + 1, 1) AS rn,
            @prev := groupname
        FROM mytable
        JOIN (SELECT @prev := NULL, @rn := 0) AS vars
        ORDER BY groupname, age DESC, person
    ) AS T1
    WHERE rn <= 2

    在线演示: sqlfiddle


    编辑 我刚刚注意到bluefeet发布了一个非常相似的答案:给他+1。但是这个答案有两个小优点:

    1. 这是一个单一查询。变量在SELECT语句内部初始化。
    2. 它处理了问题中描述的并列情况(按名称的字母顺序)。

    因此,我将保留它,以防它能帮助到某人。

    Antwort
    0
  • P粉404539732

    P粉4045397322023-08-22 13:19:02

    以下是一种方法,使用UNION ALL(请参见带有演示的SQL Fiddle)。这适用于两个组,如果你有多个组,则需要指定group编号并为每个group添加查询:

    (
      select *
      from mytable 
      where `group` = 1
      order by age desc
      LIMIT 2
    )
    UNION ALL
    (
      select *
      from mytable 
      where `group` = 2
      order by age desc
      LIMIT 2
    )

    有多种方法可以实现这个目标,请参考本文以确定适合您情况的最佳方法:

    http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/

    编辑:

    这也可能适用于您,它为每条记录生成一个行号。使用上面链接中的示例,它将仅返回行号小于或等于2的记录:

    select person, `group`, age
    from 
    (
       select person, `group`, age,
          (@num:=if(@group = `group`, @num +1, if(@group := `group`, 1, 1))) row_number 
      from test t
      CROSS JOIN (select @num:=0, @group:=null) c
      order by `Group`, Age desc, person
    ) as x 
    where x.row_number <= 2;

    请参见演示

    Antwort
    0
  • StornierenAntwort