SQL SELECT с накопительным вычислением по выбранным строкам - PullRequest
0 голосов
/ 04 апреля 2019

Всем привет и заранее большое спасибо за вашу помощь.

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

Для первого вхождения каждого АРТИКУЛ И ЦВЕТ И РАЗМЕР CALCULATEDSTOCK - это «начальный» STOCK, а для второго и следующего экземпляров того же ARTICLE & COLOR & SIZE CALCULATEDSTOCK уменьшается на предыдущие единицы NEEDED, поэтому я получаю доступный запас дляэта строка.

Обратите внимание, что STOCK всегда совпадает с прямым запросом к базе данных.

Вот результаты, которые я хотел бы получить:

ORDER   ARTICLE  COLOR    SIZE   STOCK   NEEDED   CALCULATEDSTOCK
-----------------------------------------------------------------
43002   1000     GREY     L      13      4        13
43002   1000     GREY     XL     20      5        20
43006   1000     GREY     XL     20      4        15 
43012   1000     GREY     XL     20      6        11
43021   1000     GREY     XL     20      2        5
43021   1000     PURPLE   M      7       2        7
43023   1000     PURPLE   L      6       3        6

Ниже найдите то, что я пробовал, но я не могу применить команду LAG к предыдущему столбцу CALCULATEDSTOCK, поэтому я не могу рассчитать более двух строк ...

SELECT ORDER, ARTICLE, COLOR, SIZE, STOCK, NEEDED,
CAST( CASE WHEN ARTICLE = LAG(ARTICLE) OVER (ORDER BY ARTICLE, COLOR, SIZE, ORDER)
   AND COLOR = LAG(COLOR) OVER (ORDER BY ARTICLE, COLOR, SIZE, ORDER)
   AND SIZE = LAG(SIZE) OVER (ORDER BY ARTICLE, COLOR, SIZE, ORDER)
THEN 
(lag(STOCK) OVER (ORDER BY ARTICLE, COLOR, SIZE, ORDER))
-(lag(NEEDED) OVER (ORDER BY ARTICLE, COLOR, SIZE, ORDER))

ELSE STOCK
END
AS decimal(8, 2)) AS CALCULATEDSTOCK
.....

В примере три строкизаказов того же ARTICLE & COLOR & SIZE, но их может быть больше ...

Большое спасибо за ваше терпение и сладкие приветствия!

Ответы [ 2 ]

0 голосов
/ 04 апреля 2019

Может быть более элегантный способ сделать это, но вот один из вариантов:

; with CTE as (select *
    , stock - sum(needed) over (partition by ARTICLE, color, size order by ORDER) as CalcNeeded
    , lead(ORDER) over (partition by ARTICLE, color, size order by ORDER) as PrevOrder
from MyTable)

select a.ORDER,
       a.ARTICLE,
       a.color,
       a.size,
       a.stock,
       a.needed,
       ISNULL(b.CalcNeeded, a.stock)
from cte a
left join cte b
on a.ARTICLE= b.ARTICLE and a.color = b.color and a.size = b.size
and a.ORDER = b.PrevOrder
0 голосов
/ 04 апреля 2019

Я думаю, что вам не хватает PARTITION. Кроме того, LAG отлично, но если вы просто делаете тип промежуточного итога, SUM с небольшим количеством вычислений будет хорошо. Во-первых, вам понадобится идентификатор в ваших исходных данных; повторяющиеся столбцы испортят его.

with source (ORDER_id,   ARTICLE,  COLOR ,   SIZE,   STOCK,   NEEDED) as
(
select 43002,   1000   ,  'GREY  ',   'L '  ,   13   ,   4 union all 
select 43002,   1000   ,  'GREY  ',   'XL'  ,   20   ,   5 union all 
select 43006,   1000   ,  'GREY  ',   'XL'  ,   20   ,   4 union all 
select 43012,   1000   ,  'GREY  ',   'XL'  ,   20   ,   6 union all 
select 43021,   1000   ,  'GREY  ',   'XL'  ,   20   ,   2 union all 
select 43021,   1000   ,  'PURPLE',   'M '  ,   7    ,   2 union all 
select 43023,   1000   ,  'PURPLE',   'L '  ,   6    ,   3 
)
select id, order_id, article, color, size, stock, NEEDED, stock + needed - sum(needed) over (partition by ARTICLE, COLOR, SIZE order by id)
from (
    select row_number() over (order by order_id) id, ORDER_id, ARTICLE, COLOR, SIZE, STOCK, NEEDED
    from source
) source_with_id
...