每两行运行计数

时间:2017-03-29 06:13:58

标签: sql sql-server sql-server-2012

我正在尝试计算每个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。

3 个答案:

答案 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的要求。

Demo here

编辑:

为了抵消更大的记录组尝试使用(信用转到@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
--------------------------------------