【问题标题】:SQL-select top 3 values per group WITH CONDITIONSQL-select 每组的前 3 个值 WITH CONDITION
【发布时间】:2023-03-16 16:21:01
【问题描述】:

我想为每个标签提取不同产品类别的前 3 名畅销产品。 数据如下所示:

tag  | product_name | product_category | order_count
tag1 | product1     | category1        | 100
tag1 | product2     | category2        | 80
tag1 | product3     | category2        | 60
tag1 | product4     | category3        | 50
......

我知道如何使用 ROW_NUMBER() 提取每个标签的前 3 个畅销产品,但它会返回 product1、product2、product3。我不想要 product3,因为它与 product2 属于同一类别。我想要 product4 代替。如何在 SQL Server 中做到这一点?

【问题讨论】:

    标签: sql sql-server greatest-n-per-group


    【解决方案1】:

    第一个 ROW_NUMBER 删除每个标签和 product_category 的重复行,第二个 ROW_NUMBER 选择每个标签的前 3 个畅销产品

    ;WITH cte AS
     (SELECT *, ROW_NUMBER() OVER(PARTITION BY tag, product_category ORDER BY order_count DESC) AS rn
      FROM yourtable
      ), cte2 AS
      (SELECT *, ROW_NUMBER() OVER(PARTITION BY tag ORDER BY order_count DESC) AS rn2
       FROM cte
       WHERE rn = 1
       )
       SELECT *
       FROM cte2
       WHERE rn2 <= 3
    

    SQLFiddle上的演示

    下一个使用派生表

    ;WITH cte AS
     (SELECT t2.tag, t2.product_name, t2.product_category, t2.order_count,
             ROW_NUMBER() OVER(PARTITION BY t2.tag ORDER BY order_count DESC) AS rn
      FROM (SELECT tag, product_category, MAX(order_count) AS maxCount
            FROM yourtable
            GROUP BY tag, product_category
            ) t1 JOIN yourtable t2 ON t1.tag = t2.tag 
              AND t1.product_category = t2.product_category
              AND maxCount = order_count
      )
      SELECT *
      FROM cte
      WHERE rn <= 3
    

    SQLFiddle上的演示

    【讨论】:

      【解决方案2】:

      只要使用PARTITION BY,就可以使用RANK()(或ROW_NUMBER())。假设您使用的是 SQL Server 2005+,则与 TOP() 结合使用应该可以很好地工作:

      with cte as (
        select tag, 
          product_name, 
          product_category, 
          order_count, 
          rank() over (partition by product_category 
                       order by product_category, order_count desc) rnk
        from yourtable
        )
      select top 3 tag, product_name, product_category, order_count
      from cte 
      where rnk = 1
      order by order_count desc
      

      这将产生以下内容:

      TAG     PRODUCT_NAME   PRODUCT_CATEGORY  ORDER_COUNT
      tag1    product1       category1         100
      tag1    product2       category2         80
      tag1    product4       category3         50
      

      【讨论】:

        【解决方案3】:

        我建议只用一个选择

        declare @t table (
            tag                 varchar(10),
            product_name        varchar(10),
            product_category    varchar(10),
            order_count         int
        );
        
        insert into @t values
        ('tag1', 'product1', 'category1', 100),
        ('tag1', 'product2', 'category2', 80 ),
        ('tag1', 'product3', 'category2', 60 ),
        ('tag1', 'product4', 'category3', 50 ),
        ('tag1', 'product5', 'category4', 40 );
        
        
        select top 3
            *
        from
            @t
        order by
            row_number() over(partition by product_category order by order_count desc), 
            order_count desc;
        

        SQL Fiddle

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-27
          • 1970-01-01
          • 1970-01-01
          • 2016-12-08
          • 2014-04-06
          • 1970-01-01
          相关资源
          最近更新 更多