我在SQL Server 2012中工作。我有以下简单表:
CREATE TABLE t
(
NK1 varchar(255)
,NK2 varchar(255)
,ID int
,amount decimal(10,2)
);
INSERT INTO t
SELECT 'a', 'x', 3, 10.00 UNION ALL
SELECT 'a', 'x', 1, 5.00 UNION ALL
SELECT 'a', 'x', 0, 15.00 UNION ALL
SELECT 'a', 'y', 1, 0.00 UNION ALL
SELECT 'a', 'y', 10, -5.00 UNION ALL
SELECT 'b', 'x', 2, 10.00 UNION ALL
SELECT 'b', 'y', 0, 0.00 UNION ALL
SELECT 'b', 'y', -1, 15.00 UNION ALL
SELECT 'b', 'y', 3, 10.00 UNION ALL
SELECT 'b', 'y', 15, 10.00;
列NK1
和NK2
定义表的自然键。我的目标是返回最大行号(对于每个自然键:ORDER BY NK1 ASC, NK2 ASC, ID ASC
),相应的amount
值以及每个自然键的amount
列的总和。
因此,对于给定的表,我期望得到以下结果集:
NK1 || NK2 || max_RowNumber || amount || sum_amount
a | x | 1 | 10.00 | 30.00
a | y | 2 | -5.00 | -5.00
b | x | 1 | 10.00 | 10.00
b | y | 4 | 10.00 | 35.00
我在单个SELECT
语句中使用2个以上的聚合函数时遇到了麻烦(显然,在2个以上的不同列上)。
这是我的尝试:
WITH cte AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY NK1, NK2 ORDER BY NK1, NK2, ID) AS RowNumber
FROM
t
)
SELECT
NK1, NK2,
MAX(RowNumber) AS max_RowNumber,
amount,
SUM(amount) AS sum_amount
FROM
cte
GROUP BY
NK1, NK2;
当我运行上述查询时,出现以下错误:
关键字'From'附近的语法不正确。
它指的是“FROM cte
”行。我相信这是因为SELECT
中不同列上的2+聚合函数。
特别是,“SUM
”行表示
'SUM'不是公认的内置函数名称。
如何解决此问题?
答案 0 :(得分:2)
我得到了一个不同的错误:
列'cte.amount'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。
从查询中删除,amount
时,它可以正常工作:
;
WITH cte AS
(
SELECT
*
,ROW_NUMBER() OVER (
PARTITION BY
NK1
,NK2
ORDER BY
NK1
,NK2
,ID
) AS RowNumber
FROM
t
)
SELECT
NK1
,NK2
,MAX(RowNumber) AS max_RowNumber
,SUM(amount) AS sum_amount
FROM
cte
GROUP BY
NK1
,NK2
;
结果:
NK1 NK2 max_RowNumber sum_amount
a x 3 30,00
b x 1 10,00
a y 2 -5,00
b y 4 35,00
答案 1 :(得分:0)
错误是由于您的最终SELECT
语句包含amount
,但amount
中不存在GROUP BY
。
如果您从最终查询中取出amount
(而不是SUM(amount)
,则可以正常使用。
WITH cte AS (
SELECT *
,ROW_NUMBER() OVER (
PARTITION BY
NK1
,NK2
ORDER BY
NK1
,NK2
,ID
) AS RowNumber
FROM
t
)
SELECT
NK1
,NK2
,MAX(RowNumber) AS max_RowNumber
,SUM(amount) AS sum_amount
FROM cte
GROUP BY
NK1
,NK2;
结果:
NK1 NK2 max_RowNumber sum_amount
---- ---- -------------- ----------
a x 3 30.00
b x 1 10.00
a y 2 -5.00
b y 4 35.00
答案 2 :(得分:0)
我已经赞同Zohar的答案,因为他首先清除了错误,但我想知道你为什么这样使用row_number()
:
with cte as (
select *
, row_number() over (
partition by NK1, NK2
order by NK1, NK2,ID /* NK1, NK2 don't do anything here either */
) as RowNumber
from t
)
select
NK1
, NK2
, max(RowNumber) as max_RowNumber
, sum(amount) as sum_amount
from cte
group by NK1, NK2;
这与此不一样?
select
NK1
, NK2
, count(*) as max_RowNumber
, sum(amount) as sum_amount
from t
group by NK1, NK2;
rextester演示显示相同的结果:http://rextester.com/XSGIP25353
答案 3 :(得分:0)
我建议采用下一种方法:
CTE计算RANK()(或ROW_NUMBER),但我按NK1,NK2排序, ID DESC 它允许INNER JOIN与t表WHERE RowNumber = 1,因此您可以获得ID和最大行号的数量。
WITH ctMax AS
(
SELECT NK1,
NK2,
ID,
RANK() OVER (PARTITION BY NK1, NK2 ORDER BY NK1, NK2, ID DESC) AS RK
FROM t
)
SELECT t.NK1, t.NK2, t.ID, t.amount,
(SELECT SUM(amount)
FROM t t2
WHERE t2.NK1 = t.NK1
AND t2.NK2 = t.NK2) as TotalAmount
FROM t
INNER JOIN ctMax cm
ON t.NK1 = cm.NK1
AND t.NK2 = cm.NK2
AND t.ID = cm.ID
WHERE cm.RK = 1;
NK1 | NK2 | ID | amount | TotalAmount
:-- | :-- | -: | :----- | :----------
a | x | 3 | 10.00 | 30.00
a | y | 10 | -5.00 | -5.00
b | x | 2 | 10.00 | 10.00
b | y | 15 | 10.00 | 35.00
dbfiddle here