Запуск подсчета для каждых 2 рядов
Я пытаюсь подсчитать количество запусков для каждых 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.
Ответы
Ответ 1
Выражение:
SUM(Sales) OVER (PARTITION BY empid
ORDER BY empid
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
вычисляет сумму, считая текущую строку и две строки, непосредственно предшествующие ей. Таким образом, он фактически вычисляет скользящую сумму, чего вы действительно не хотите.
Я думаю, что вы действительно ищете что-то вроде следующего:
;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
, 2
для следующих двух записей, и т.д.
Используя grp
, мы можем вычислить текущее общее число sales
для групп из 2, как и требование OP.
Демо здесь
Edit:
Чтобы компенсировать большую группу записей, попробуйте использовать (кредит указывается @Max Szczurek для указания этого):
(ROW_NUMBER() OVER (PARTITION BY empid ORDER BY yr) - 1 ) / n AS grp
где n
- количество записей, содержащихся в каждой группе.
Ответ 2
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
Отмена возвращает значение предыдущей строки - когда row_number() равно, добавьте текущее значение строки в предыдущую строку - иначе просто покажите продажи текущей строки. Разделение каждого по EmpId, упорядочение каждого по yr - выход соответствует ожидаемому.
Кроме того, большое спасибо за добавление данных DDL/sample.
Ответ 3
Хотя ответ уже принят, рассмотрите также и запрос ниже. Это даст требуемый результат:
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
OUTPUT
--------------------------------------
--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
--------------------------------------