我有一些如下记录:
ID Val Amount
1 0 3
2 0 3
3 0 4
4 1 2
5 1 3
6 2 3
7 2 4
我想通过列Val对这些数据进行分组并得到总和(金额),但不要对Val = 0的那些进行分组。
我需要的结果集如下:
Val Amount
0 3
0 3
0 4
1 5
2 7
我通过两种方式做到了,但似乎没有一种方法:
第一个是使用联合,例如,首先使用Val = 0的联合,然后将这些联合分组为Val<>。 0并将两个结果集合并。
第二个更好一点。让我们调用表中的数据@Table:
WITH g AS
(
SELECT Val, Amount, CASE WHEN Val = '0' then Val + ID
else Val END A FROM @table
)
SELECT CASE WHEN A LIKE '0%' THEN 0 ELSE A END AS A, SUM(Amount)
FROM g
GROUP BY A
这也有效,但是必须与ID列(或raw_number)连接,而不是使用left函数来删除它不是最佳做法。
因此,我正在寻找更好的方法,既看起来更好,也表现更好。
我在SQL Server 2008上工作,但我对任何需要更新版本的解决方案持开放态度。
答案 0 :(得分:2)
在这里使用联盟。下面联合的顶部找到不为零的值的总量,底部带来零值记录,而不是聚合。
SELECT Val, SUM(Amount) AS Amount
FROM g
WHERE Val <> 0
GROUP BY Val
UNION ALL
SELECT Val, Amount
FROM g
WHERE Val = 0
ORDER BY Val;
答案 1 :(得分:2)
最简单的方法如下:
SELECT Val, SUM(Amount)
FROM mytable
GROUP BY Val, CASE WHEN Val = 0 THEN ID ELSE 0 END
您也可以使用窗口功能来执行此操作:
;WITH CTE AS (
SELECT ID, Val, Amount,
DENSE_RANK() OVER (PARTITION BY Val
ORDER BY CASE
WHEN Val = 0 THEN ID
ELSE 0
END) AS rank
FROM mytable
)
SELECT Val, SUM(Amount) AS total_amount
FROM CTE
GROUP BY Val, rank
CTE
返回的结果集是:
ID Val Amount rank
--------------------
1 0 3 1
2 0 3 2
3 0 4 3
4 1 2 1
5 1 3 1
6 2 3 1
7 2 4 1
因此,使用rank
,您可以区分0
和其他Val
值。
您可以使用这两种方法,并了解它们在性能方面相互比较的方式。