2016-04-23 2 views
3

Я пытаюсь сверлить значения продуктов на основе дат. Пример ниже начинается с 20 000, добавляет 5000, а затем вычитает 7 000. Результат должен питаться через все 5000, а затем в предыдущий положительный ряд. Это удалит 5000 строк.SQL Aggregate Sum только для Net Out Отрицательные строки

Я думаю, что это было бы так же просто, как сделать функцию окна суммы, упорядоченную по дате по убыванию. Однако, как вы можете видеть ниже, я хочу прекратить суммирование в любой строке, которая остается положительной, а затем перейти к следующей.

Я не могу понять логику SQL, чтобы сделать эту работу. В моей голове, должно быть:

SUM(Value) OVER (PARTITION BY Product, (positive valued rows) ORDER BY Date DESC) 

Но может быть несколько положительных значных строк в строке, где отрицательная значных строка может съесть через все из них, или там может быть несколько отрицательных значений в строке.

This post представляется многообещающим, но я не думаю, что логика будет работать, если отрицательное значение будет больше, чем положительное значение.

ИМЕЮТ:

+------------+----------------+-------+ 
| Date | Product  | Value | 
+------------+----------------+-------+ 
| 01/13/2015 | Prod1   | 20000 | 
| 08/13/2015 | Prod1Addition1 | 5000 | 
| 12/13/2015 | Prod1Removal | -7000 | 
| 02/13/2016 | Prod1Addition2 | 2000 | 
| 03/13/2016 | Prod1Addition3 | 1000 | 
| 04/13/2016 | Prod1Removal | -1500 | 
+------------+----------------+-------+ 

ХОТИТЕ:

+------------+----------------+-------+ 
| Date | Product  | Value | 
+------------+----------------+-------+ 
| 01/13/2015 | Prod1   | 18000 | 
| 02/13/2016 | Prod1Addition2 | 1500 | 
+------------+----------------+-------+ 

ответ

2

я могу думать только о рекурсивном решении CTE

; with 
cte as 
(
    select Date, Product, Value, rn = row_number() over (order by Date) 
    from yourtable 
), 
rcte as 
(
    select Date, Product, Value, rn, grp = 1 
    from cte 
    where rn = 1 
    union all 
    select Date = case when r.Value < 0 then c.Date else r.Date end, 
     Product = case when r.Value < 0 then c.Product else r.Product end, 
     c.Value, 
     c.rn, 
     grp = case when r.Value < 0 then r.grp + 1 else r.grp end 
    from rcte r 
     inner join cte c on r.rn = c.rn - 1 
) 
select Date, Product, Value = sum(Value) 
from rcte 
group by Date, Product, grp  
order by Date 
+0

Я боялся рекурсивного CTE из-за проблем с производительностью. Будет ли это что-то делать в процессе ETL, прежде чем даже запросить данные? – houstonwp

+0

независимо от проблемы с производительностью, это стоит одного голоса от меня. Для OP вы можете попробовать использовать некоторое решение с CURSOR, если хотите повысить производительность. Уверен, у вас нет выбора для решения этой проблемы, это какая-то сложная проблема. Одно из возможных решений (которое легко и эффективно работает) - попробуйте использовать некоторую пользовательскую функцию .NET, вы создаете эту функцию в некоторой сборке .NET, используйте ее в своем запросе. Функция .NET позволяет использовать некоторую статическую переменную, поэтому вы можете легко определить ее, чтобы вернуть ключ для группировки. –

+0

@KingKing Есть ли у вас какие-либо ссылки на документацию и примеры, которые могут показать мне, что вы имеете в виду? Я согласен, что реакция Белки очень важна для этой проблемы. – houstonwp

-1

Я думаю, что вы хотите:

select Date, 
     Product, 
     Sum(Value) As Value 
    From TABLE_NAME 
Group By Date, Product 
Order by Date, Product; 

то будет правильно?

+0

Нет, это группировка по датам, а также даты различны для каждого добавления и удаления. – houstonwp

Смежные вопросы