【问题标题】:SQL — take Top 3 values from GROUP BYSQL — 从 GROUP BY 中获取前 3 个值
【发布时间】:2020-11-04 08:21:37
【问题描述】:

小提琴:https://www.db-fiddle.com/f/9F7XPiGtuQAYXQ99HfNJGN/3

CREATE TABLE table_1 (
  `country` VARCHAR(2),
  `category` VARCHAR(2),
  `cnt` INT
);

INSERT INTO table_1
  (`country`, `category`, `cnt`)
VALUES
  ('US', 'AA', 20),
  ('US', 'BB', 15),
  ('US', 'CC', 25),
  ('US', 'DD', 30),
  ('FR', 'AA', 10),
  ('FR', 'BB', 5),
  ('FR', 'CC', 50),
  ('FR', 'DD', 60);

这是数据:


| country | category | cnt |
| ------- | -------- | --- |
| FR      | DD       | 60  |
| FR      | CC       | 50  |
| FR      | AA       | 10  |
| FR      | BB       | 5   |
| US      | DD       | 30  |
| US      | CC       | 25  |
| US      | AA       | 20  |
| US      | BB       | 15  |

我想获取每个国家/地区的前 3 行(前 3 个类别),按 cnt 列排序。例如,我想要:

| country | category | cnt |
| ------- | -------- | --- |
| FR      | DD       | 60  |
| FR      | CC       | 50  |
| FR      | AA       | 10  |
| US      | DD       | 30  |
| US      | CC       | 25  |
| US      | AA       | 20  |

该表尚未由 cnt 订购。我尝试过 LIMIT 3 或 TOP 3,但它并没有达到我想要的效果/总体上给了我前 3 名,但不是针对每个国家/地区。

【问题讨论】:

    标签: sql group-by presto


    【解决方案1】:

    你可以使用row_number():

    select t.*
    from (select t.*, row_number() over (partition by country order by cnt desc) as seqnum
          from t
         ) t
    where seqnum <= 3;
    

    【讨论】:

      【解决方案2】:

      你可以通过dense_rank()得到你的结果

      select 
        *
      from 
      (
        select 
          *, 
          dense_rank() over (partition by country order by cnt desc) as rn
        from yourTable
      ) subq
      where rn <= 3
      

      【讨论】:

        【解决方案3】:

        请使用以下查询,

        select country, category, cnt from
        (select country, category, cnt, row_number() over(partition by country order by cnt 
        desc) as rnk from table_1) qry
        where rnk between 1 and 3;
        

        演示:

        【讨论】:

          【解决方案4】:

          我认为这里可以使用另一个概念,很高兴知道它。

          您可以使用maxmax_by函数,并使用两个函数获取的附加参数n,该参数表示返回n个值。见docs

          所以你的查询看起来像:

          SELECT country, max(cnt,3) top3_cnt, max_by(category,cnt,3) top3_category
          FROM table_1
          GROUP BY country
          
          -------
          Results:
          country  top3_cnt       top3_category
          FR       [60, 50, 10]   [DD, CC, AA]
          US       [30, 25, 20]   [DD, CC, AA]
          

          顺便说一句,我喜欢使用WITH 使用命名表创建测试数据。而不是真正创建表和插入数据。

          因此,对于这个查询,您可以将其用于测试目的:

          WITH table_1 (country,category,cnt) AS ( 
           SELECT * FROM (VALUES
            ('US', 'AA', 20),
            ('US', 'BB', 15),
            ('US', 'CC', 25),
            ('US', 'DD', 30),
            ('FR', 'AA', 10),
            ('FR', 'BB', 5),
            ('FR', 'CC', 50),
            ('FR', 'DD', 60) ))
          

          【讨论】:

            猜你喜欢
            • 2018-03-29
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-11-13
            • 1970-01-01
            • 1970-01-01
            • 2018-06-04
            • 1970-01-01
            相关资源
            最近更新 更多