聚合顶部以外的行
Aggregate rows outside the top
假设我们有以下水果 table:
Fruit | Qty
-------------
Apple | 2
Apple | 5
Apple | 2
Orange | 3
Orange | 4
Orange | 0
Banana | 2
Banana | 5
Pear | 2
Mango | 1
Mango | 0
如果我想获得前 3 个水果,我会创建这样的查询:
SELECT TOP 3 Fruit, SUM(Qty) AS Total
FROM Fruits
GROUP BY Fruit
ORDER BY Total DESC
将return:
Apple | 9
Orange | 7
Banana | 7
但是,如果我想包括不在前 3 名的水果的总和,我将不得不使用 NOT IN
编写这样的代码来排除前 3 名水果:
SELECT 'OTHER' AS Fruit, SUM(Qty) AS Total
FROM Fruits
WHERE Fruit NOT IN (SELECT Fruit FROM (SELECT TOP 3 Fruit, SUM(Qty) AS Total FROM Fruits GROUP BY Fruit ORDER BY Total DESC) AS Test)
如果我想在单个查询中执行此操作,我想我可以使用 UNION
组合这两个查询。我已经有了 B 计划,但我想知道 SQL 是否有任何内置方法来聚合不属于可用于简化查询的最高值的行?
这是根据 sum(qty)
.
对行进行排名的一种方法
with totals as (SELECT Fruit, SUM(Qty) AS Total FROM Fruits GROUP BY Fruit)
, rownums as (select *, dense_rank() over(order by total desc) as rank from totals)
select
case when rank > 3 then 'Other' else fruit end as fruit, total
from rownums
如果 other
行需要聚合,请在 total
列和 group by
case
语句中再包含一个 sum
。
您需要对总和进行排序,并为最终结果添加另一个 SUM:
with cte as
(
SELECT Fruit, SUM(Qty) AS Qty,
ROW_NUMBER() OVER (ORDER BY SUM(Qty) DESC) AS rn
FROM Fruits
GROUP BY Fruit
)
select
case when rn > 3 then 'Other' else fruit end as fruit,
sum(Qty)
from cte
group by
case when rn > 3 then 'Other' else fruit end
order by MIN(rn)
几乎!,很遗憾你不能把排名放在一边!!但你不能。所以你必须有一个嵌套的 select 然后是一个 where.
加上这种方法,您可以获得任何您想要的组,即 BETWEEN AND 3.. > 3 .. IN(1,3,6) 等
DECLARE @Fruits TABLE (Fruit NVARCHAR(32),Qty INT)
INSERT INTO @Fruits(Fruit,Qty)
VALUES
('Apple',2),
('Apple',5),
('Apple',2),
('Orange',3),
('Orange',4),
('Orange',0),
('Banana',2),
('Banana',5),
('Pear',2),
('Mango',1),
('Mango',0)
SELECT TOP 3 Fruit, SUM(Qty) AS Total
FROM @Fruits
GROUP BY Fruit
ORDER BY Total DESC
SELECT A.Fruit,A.Total FROM
(
SELECT Fruit, SUM(Qty) AS Total,RANK() OVER (ORDER BY SUM(Qty) DESC,Fruit) AS GroupNumber
FROM @Fruits
GROUP BY Fruit
) AS A
WHERE GroupNumber > 3 --This bit lets you pick the groups!
ORDER BY Total DESC
假设我们有以下水果 table:
Fruit | Qty
-------------
Apple | 2
Apple | 5
Apple | 2
Orange | 3
Orange | 4
Orange | 0
Banana | 2
Banana | 5
Pear | 2
Mango | 1
Mango | 0
如果我想获得前 3 个水果,我会创建这样的查询:
SELECT TOP 3 Fruit, SUM(Qty) AS Total
FROM Fruits
GROUP BY Fruit
ORDER BY Total DESC
将return:
Apple | 9
Orange | 7
Banana | 7
但是,如果我想包括不在前 3 名的水果的总和,我将不得不使用 NOT IN
编写这样的代码来排除前 3 名水果:
SELECT 'OTHER' AS Fruit, SUM(Qty) AS Total
FROM Fruits
WHERE Fruit NOT IN (SELECT Fruit FROM (SELECT TOP 3 Fruit, SUM(Qty) AS Total FROM Fruits GROUP BY Fruit ORDER BY Total DESC) AS Test)
如果我想在单个查询中执行此操作,我想我可以使用 UNION
组合这两个查询。我已经有了 B 计划,但我想知道 SQL 是否有任何内置方法来聚合不属于可用于简化查询的最高值的行?
这是根据 sum(qty)
.
with totals as (SELECT Fruit, SUM(Qty) AS Total FROM Fruits GROUP BY Fruit)
, rownums as (select *, dense_rank() over(order by total desc) as rank from totals)
select
case when rank > 3 then 'Other' else fruit end as fruit, total
from rownums
如果 other
行需要聚合,请在 total
列和 group by
case
语句中再包含一个 sum
。
您需要对总和进行排序,并为最终结果添加另一个 SUM:
with cte as
(
SELECT Fruit, SUM(Qty) AS Qty,
ROW_NUMBER() OVER (ORDER BY SUM(Qty) DESC) AS rn
FROM Fruits
GROUP BY Fruit
)
select
case when rn > 3 then 'Other' else fruit end as fruit,
sum(Qty)
from cte
group by
case when rn > 3 then 'Other' else fruit end
order by MIN(rn)
几乎!,很遗憾你不能把排名放在一边!!但你不能。所以你必须有一个嵌套的 select 然后是一个 where.
加上这种方法,您可以获得任何您想要的组,即 BETWEEN AND 3.. > 3 .. IN(1,3,6) 等
DECLARE @Fruits TABLE (Fruit NVARCHAR(32),Qty INT)
INSERT INTO @Fruits(Fruit,Qty)
VALUES
('Apple',2),
('Apple',5),
('Apple',2),
('Orange',3),
('Orange',4),
('Orange',0),
('Banana',2),
('Banana',5),
('Pear',2),
('Mango',1),
('Mango',0)
SELECT TOP 3 Fruit, SUM(Qty) AS Total
FROM @Fruits
GROUP BY Fruit
ORDER BY Total DESC
SELECT A.Fruit,A.Total FROM
(
SELECT Fruit, SUM(Qty) AS Total,RANK() OVER (ORDER BY SUM(Qty) DESC,Fruit) AS GroupNumber
FROM @Fruits
GROUP BY Fruit
) AS A
WHERE GroupNumber > 3 --This bit lets you pick the groups!
ORDER BY Total DESC