首頁  >  問答  >  主體

抓取每個分組結果中的前n筆記錄

<p>以下是最簡單的可能範例,但任何解決方案都應能夠擴展到所需的n個頂部結果:</p> <p>給定以下表格,其中包含人員、組別和年齡列,如何取得每個組別中年齡最大的2個人? (組內的並列情況不應產生更多結果,而是按字母順序給出前2個)</p> <pre> -------- ------- ----- | Person | Group | Age | -------- ------- ----- | Bob | 1 | 32 | | Jill | 1 | 34 | | Shawn | 1 | 42 | | Jake | 2 | 29 | | Paul | 2 | 36 | | Laura | 2 | 39 | -------- ------- ----- </pre> <p>期望的結果集:</p> <pre> -------- ------- ----- | Shawn | 1 | 42 | | Jill | 1 | 34 | | Laura | 2 | 39 | | Paul | 2 | 36 | -------- ------- ----- </pre> <hr> <p><strong>注意:</strong>這個問題是基於之前的一個問題——獲取每個組的最大值的記錄的SQL結果- 用於獲取每個組的單個頂部行,並且從@Bohemian獲得了一個很好的MySQL特定的答案:</p> <pre class="brush:php;toolbar:false;">select * from (select * from mytable order by `Group`, Age desc, Person) x group by `Group`</pre> <p>很想能夠在此基礎上繼續構建,但我看不出如何做到。 </p>
P粉785957729P粉785957729447 天前425

全部回覆(2)我來回復

  • 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. 它處理了問題中描述的並列情況(按名稱的字母順序)。

    因此,我將保留它,以防它能幫助某人。

    回覆
    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;

    請參考演示

    #

    回覆
    0
  • 取消回覆