如何根据条件选择每个组的 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 成员的主要内容,如果未能解决你的问题,请参考以下文章