如何根据条件选择每个组的 x 或 y 成员

Posted

技术标签:

【中文标题】如何根据条件选择每个组的 x 或 y 成员【英文标题】:How to select x or y members of each group based on a condition 【发布时间】:2017-03-16 21:03:15 【问题描述】:

使用 SQL Server 2012。我在一个表中有数千个组,我需要能够选择 everything but top member 或 everything but top two每个组的成员基于每个组成员拥有的数量。这些组没有被显式调用,但我可以使用窗口函数分配组号。为了说明我的问题,这里有一些示例数据:

Group   Attribute   ProductClass Product    Quantity
1       abc         xaxa         xx1000     16
1       abc         xaxa         xx1019     15
1       def         xaxa         xx1938     13
1       abc         xaxa         xx1021     10
2       def         xaxa         xx1031     18
2       def         xaxa         xx3013     17
2       abc         xaxa         xx4810     14
3       abc         xaxb         xx0110     18
3       def         xaxb         xx3810     15
3       def         xaxb         xx2010     11
3       def         xaxb         xx1002     8
3       def         xaxb         xx1040     2
3       abc         xaxb         xx0023     2
4       def         xaxb         xx4918     14
4       abc         xaxb         xx1414     11
4       abc         xaxb         xx4182     11
4       def         xaxb         xx1004     2

这是所需的输出:

Group   Attribute   ProductClass Product    Quantity
1       def         xaxa         xx1938     13
1       abc         xaxa         xx1021     10
2       def         xaxa         xx3013     17
2       abc         xaxa         xx4810     14
3       def         xaxb         xx2010     11
3       def         xaxb         xx1002     8
3       def         xaxb         xx1040     2
3       abc         xaxb         xx0023     2
4       abc         xaxb         xx1414     11
4       abc         xaxb         xx4182     11
4       def         xaxb         xx1004     2

“属性”列中只有两个属性。请注意,对于“abc”,我想要数量最多的两个产品,而对于“def”,我只想要数量最多的产品。

我创建的代码可以选择所有内容,但每个组的顶行,以及可以分配组名称的代码。我只是无法超越这部分:

SELECT 
      p.Group,
      p.Attribute,
      p.ProductClass,
      p.Product,
      p.Quantity
 FROM (SELECT *,
              ROW_NUMBER() OVER(PARTITION BY ProductClass, Product ORDER BY Quantity DESC) AS RowNum,
              DENSE_RANK() OVER(ORDER BY ProductClass, Product) AS Group
         FROM table
        WHERE brand = 'brand') AS p
WHERE RowNum > 1;

请注意,ProductClass 和 Product 共同创建了唯一的分组。

提前非常感谢!

【问题讨论】:

您的代码实际上得到了除了每组中的第一行,但它已经足够接近了。 @GordonLinoff,感谢您指出这一点。这实际上是我想要的行为。我编辑了帖子以反映这一点。 【参考方案1】:

Rank() 而不是row_number() 几乎可以让你到达那里。问题是这些行并列第二名,而不是第三名。

SELECT p.Group, p.Attribute, p.ProductClass, p.Product, p.Quantity
FROM (SELECT t.*,
             RANK() OVER (PARTITION BY ProductClass, Product ORDER BY Quantity DESC) AS RowNum,
             COUNT(*) OVER (PARTITION BY ProducctClass, Product, Count) as cnt,
             DENSE_RANK() OVER (ORDER BY ProductClass, Product) AS Group
      FROM table t
      WHERE brand = 'brand'
     ) AS p
WHERE RowNum = 1 OR (RowNum = 2 AND cnt = 1);

这将获取每个组的最高值。此外,如果没有重复,并且与顶部值不匹配,它将获得第二个值。这似乎是您想要的逻辑。

【讨论】:

我在上面回复了您的评论。如果我想反转原始帖子的行为并选择除顶部结果之外的所有内容或除前两个结果之外的所有内容,那么WHERE 子句应该是什么样子? WHERE RowNum = 2 OR (RowNum > 2 AND cnt = 1)? @mowshowitz 。 . .我想应该是(RowNum > 1 OR cnt > 1)

以上是关于如何根据条件选择每个组的 x 或 y 成员的主要内容,如果未能解决你的问题,请参考以下文章

SQL选择组的第n个成员

根据多个条件选择行

根据其他列的最旧组成员的值重新编码整个组的列

根据表中每个组的唯一列选择行

Mysql如何根据优先级进行选择

如何使用套索或盒子工具选择绘图中所有字形的所有点?