#sql #sql-server #tsql #window-functions
#sql #sql-сервер #tsql #окно-функции
Вопрос:
select a, b, Volume
case
when lag(a, 1) over(order by b asc) < a then lag(c, 1) over(order by b asc) Volume
when lag(a, 1) over(order by b asc) > a then lag(c, 1) over(order by b asc) - Volume
end as c
from Table
Итак, чего я хотел бы добиться, так это … если предыдущая a
строка больше / меньше текущей a
строки, затем добавьте / вычтите Volume
из предыдущей строки c
.
if a > previous a c = previous c Volume
if a < previous a c = previous c - Volume
Но… c
Строки нет, потому что это то, что я вычисляю (поэтому c
начальное значение строки равно 0 или NULL) … в нем нет предопределенного набора данных c
. Одни данные поступают из другого… вроде того.
Если бы мне пришлось писать это на другом языке, я бы сохранил значение c
в отдельной переменной like previousRow
и переписывал бы его с каждой итерацией.
Могу ли я добиться аналогичной вещи в TSQL?
Пример данных:
a | b | Объем | c |
---|---|---|---|
1 | 2020-01 | 10 | 0 |
2 | 2020-02 | 20 | 20 |
5 | 2020-03 | 40 | 60 |
3 | 2020-04 | 30 | 30 |
1 | 2020-05 | 10 | 20 |
Комментарии:
1. Я поместил пример таблицы в вопрос. Код, который я пытаюсь, — это то, что я уже опубликовал. Вот где я застрял.
2. Его можно упорядочить по B (datetimeoffset)
3. @DaleK Вот так: investopedia.com/terms/o/onbalancevolume.asp Найдите формулу в статье
4. Все еще не действительная дата?
5. Я настоятельно рекомендую предоставить DDL DML для создания образца набора данных, чтобы он был полностью понятным.
Ответ №1:
столбец c в значительной степени сводится к условной скользящей сумме, к сожалению, sql server не допускает вложенности оконных функций, поэтому необходима производная таблица для определения предыдущего значения a. После этого суммируйте случай, когда и у вас должно быть то, что вы ищете.
Попробуйте это (добавлены дополнительные тестовые значения к набору, указанному выше):
SELECT
T.*,
SUM(
(
CASE
WHEN T.LAG_A IS NULL
THEN 0
WHEN T.A > T.LAG_A
THEN T.VOLUME
ELSE (T.VOLUME*-1)
END
)
) OVER (ORDER BY T.B ASC) AS C
FROM
(
SELECT
MY_TABLE.A,
LAG(MY_TABLE.A, 1) OVER (ORDER BY MY_TABLE.B ASC) AS LAG_A,
MY_TABLE.B,
MY_TABLE.VOLUME
FROM
(VALUES (1,CAST('1/1/2021' AS DATE),10),
(2,CAST('1/2/2021' AS DATE),20),
(5,CAST('1/3/2021' AS DATE),40),
(3,CAST('1/4/2021' AS DATE),30),
(1,CAST('1/5/2021' AS DATE),10),
(8,CAST('1/6/2021' AS DATE),50),
(4,CAST('1/7/2021' AS DATE),70)
) AS MY_TABLE(A,B,VOLUME)
) T