我正在尝试计算每个2行的运行计数,如下所示
CREATE TABLE sales
(
EmpId INT,
Yr INT,
Sales DECIMAL(8,2)
)
INSERT INTO sales (EmpId, Yr, Sales)
VALUES (1, 2005, 12000), (1, 2006, 18000), (1, 2007, 25000),
(1, 2008, 25000), (1, 2009, 25000),
(2, 2005, 15000), (2, 2006, 6000), (2, 2007, 6000)
SELECT
EmpId, Yr, sales,
SUM(Sales) OVER (PARTITION BY empid ORDER BY empid ROWS BETWEEN 2 PRECEDING AND CURRENT ROW ) AS TotalSales2
FROM
sales
输出:
EmpId Yr sales TotalSales2
-----------------------------------
1 2005 12000 12000
1 2006 18000 30000
1 2007 25000 55000
1 2008 25000 68000
1 2009 25000 75000
2 2005 15000 15000
2 2006 6000 21000
2 2007 6000 27000
但预期产出:
EmpId Yr Sales TotalSales2
-----------------------------------
1 2005 12000 12000
1 2006 18000 30000
1 2007 25000 25000
1 2008 25000 50000
1 2009 25000 25000
2 2005 15000 15000
2 2006 6000 21000
2 2007 6000 6000
我在这个查询中做错了什么?
注意:SQL Servre版本是2012。
答案 0 :(得分:16)
SELECT EmpId, Yr, Sales,
CASE WHEN ROW_NUMBER() OVER (PARTITION BY EmpId ORDER BY yr) % 2 = 0
THEN sales + lag(sales, 1, 0) OVER (PARTITION BY empid ORDER BY yr)
ELSE sales
END AS TotalSales2
FROM sales
Lag返回上一行的值 - 当row_number()为偶数时,将当前行的值添加到上一行 - 否则,只显示当前行的销售额。通过EmpId对每个进行分区,按yr排序 - 输出与预期匹配。
另外,非常感谢您添加DDL /样本数据。
答案 1 :(得分:6)
表达式:
SUM(Sales) OVER (PARTITION BY empid
ORDER BY empid
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
计算总和,考虑当前行和紧接在它之前的2行。所以它实际上计算了一个滚动总和,这是你真正不想要的。
我认为您实际上正在寻找以下内容:
;WITH CTE_Group AS (
SELECT EmpId, Yr, sales,
(ROW_NUMBER() OVER (PARTITION BY empid ORDER BY yr) + 1 ) / 2 AS grp
FROM sales
)
SELECT EmpId, Yr, sales,
SUM(sales) OVER (PARTITION BY empid, grp
ORDER BY yr) AS TotalSales2
FROM CTE_Group
以上查询使用CTE
来计算字段grp
:对于1
分区的前两个记录,此字段的值为empid
,{ {1}}用于接下来的两个记录,依此类推。
使用2
我们可以计算2个组的grp
的运行总数,这是OP的要求。
编辑:
为了抵消更大的记录组尝试使用(信用转到@Max Szczurek指出这一点):
sales
其中(ROW_NUMBER() OVER (PARTITION BY empid ORDER BY yr) - 1 ) / n AS grp
是每个组包含的记录数。
答案 2 :(得分:2)
虽然答案已被接受,但请考虑以下查询。这将提供所需的输出:
DECLARE @sales TABLE(EmpId INT, Yr INT, Sales DECIMAL(8,2))
INSERT INTO @sales ( EmpId, Yr, Sales )
VALUES (1, 2005, 12000),
(1, 2006, 18000),
(1, 2007, 25000),
(1, 2008, 25000),
(1, 2009, 25000),
(2, 2005, 15000),
(2, 2006, 6000),
(2, 2007, 6000)
;WITH SAMPLE_DATA
AS
(
SELECT ROW_NUMBER()over(partition by empid order by (select 100))SNO,* FROM @Sales
)
SELECT EmpId,Yr,Sales
,CASE WHEN (SNO%2=0)
THEN SALES+
(
SELECT Sales FROM SAMPLE_DATA T2 WHERE T2.EmpId=T1.EmpId AND T2.SNO=T1.SNO-1
)
ELSE Sales END
TotalSales2
FROM SAMPLE_DATA T1
<强>输出强>
--------------------------------------
--EmpId Yr Sales TotalSales2
--------------------------------------
1 2005 12000.00 12000.00
1 2006 18000.00 30000.00
1 2007 25000.00 25000.00
1 2008 25000.00 50000.00
1 2009 25000.00 25000.00
2 2005 15000.00 15000.00
2 2006 6000.00 21000.00
2 2007 6000.00 6000.00
--------------------------------------