У меня есть база данных транзакций SQLite. У каждого есть дата, значение и соответствующий период. Я рассчитываю определить дату, когда прибыль за период будет стерта. Вот примерная таблица.
period date value
---------- ------------- --------
1 2000-01-01 16.3
1 2000-01-02 1.5
1 2000-01-03 2.9
1 2000-01-11 32.8
2 2000-01-27 -53.5
2 2000-01-27 17.0
2 2000-01-27 94.4
2 2000-02-02 168.0
2 2000-02-05 24.7
2 2000-02-05 66.0
2 2000-02-08 60.5
2 2000-02-09 80.2
3 2000-02-22 7.3
3 2000-02-22 -510.9
3 2000-02-23 25.3
3 2000-02-25 4.2
3 2000-03-20 3.1
Для периода 1 сумма выигрышей за период составляет 16,3 + 1,5 + 2,9 + 32,8 = 53,5. Отрицательное значение -53,5 на 2000-01-27 полностью стирает эти выгоды. В идеале я хотел бы новый столбец, который суммирует эти соответствующие даты. Например,
period date value erase_date
---------- ------------- -------- -------------
1 2000-01-01 16.3 2000-01-27
1 2000-01-02 1.5 2000-01-27
1 2000-01-03 2.9 2000-01-27
1 2000-01-11 32.8 2000-01-27
2 2000-01-27 -53.5
2 2000-01-27 17.0 2000-01-27
2 2000-01-27 94.4 2000-02-22
2 2000-02-02 168.0 2000-02-22
2 2000-02-09 80.2 2000-02-22
3 2000-02-22 7.3 2000-02-22
3 2000-02-22 -510.9
3 2000-02-23 25.3 2000-02-22
3 2000-02-25 4.2 2000-02-22
3 2000-03-20 3.1 2000-02-22
Мне удалось получить то, что я ищу, используя CASE
для выделения положительных и отрицательных значений, а затем выбрав кумулятивное значение SUM
среди положительных значений, упорядоченных по столбцу периода. и кумулятивно SUM
по негативам, упорядоченным по столбцу даты, и, наконец, выбор минимальной даты, когда величина суммы суммированных негативов была больше, чем сумма суммированных позитивов. Это было очень медленно для больших таблиц (пара тысяч записей). Я надеюсь, что мне просто не хватает шаблона, который очевиден для кого-то с большим опытом использования SQL.
Вот пример кода, который я пытаюсь
WITH view AS (
SELECT
period, date, value
SUM(positive) OVER (ORDER BY period) period_positive_sum,
SUM(negative) OVER (ORDER BY date) daily_negative_sum
FROM (
SELECT
period, date, value
CASE WHEN value >= 0 THEN value END positive
CASE WHEN value < 0 THEN value END negative
FROM table
)
)
SELECT
v.period, v.date, v.value,
(SELECT
MIN(date)
FROM view
WHERE
-daily_negative_sum >= v.period_positive_sum
) erase_date
FROM view AS v