TSQL Query Расчет количества дней и количества вхождений - PullRequest
0 голосов
/ 29 октября 2019

У меня возникли проблемы при написании запроса, обобщающего некоторую информацию о запасах из запроса.

Я пробовал несколько группировок и подзапросов CTE (Common table Expressions) и функцию LAG, чтобы попытаться обобщить данные. Как ни странно, я застрял на этой проблеме в последние несколько дней.

Вот пример данных, с которыми я имею дело.

--Optional create table
--Drop table testdata
--Create table testdata ( Part int, StockDate date, OutOfStock bit);

with inventorydata(Part, StockDate, OutOfStock) as
(
  select 1000, '1/1/2019',1
  union 
  select 1000,'1/2/2019',1
  union 
  select 1000, '1/3/2019',1
  union
  select 1000, '1/4/2019',0
  union
  select 1000, '1/5/2019',1
  union 
  select 1005, '1/1/2019',0
  union 
  select 1005,'1/2/2019',1
  union 
  select 1005, '1/3/2019',1
  union
  select 1005, '1/4/2019',1
  union
  select 1005, '1/5/2019',0
)

--Insert into testdata ( Part,StockDate,OutOfStock)
Select Part,StockDate,OutOfStock from inventorydata
--Select * from testdata 

Вывод

Part        StockDate OutOfStock
----------- --------- -----------
1000        1/1/2019  1
1000        1/2/2019  1
1000        1/3/2019  1
1000        1/4/2019  0
1000        1/5/2019  1
1005        1/1/2019  0
1005        1/2/2019  1
1005        1/3/2019  1
1005        1/4/2019  1
1005        1/5/2019  0

Я пытаюсь получить желаемый вывод.

Part        StockDate BackInStock Occurance
----------- --------- ----------- -----------
1000        1/1/2019  1/3/2019    1
1000        1/5/2019  1/5/2019    1
1005        1/2/2019  1/4/2019    1

Любая помощь очень ценится. Спасибо.

1 Ответ

0 голосов
/ 30 октября 2019

Без подробностей трудно быть уверенным, что именно вы собираетесь. В желаемом выводе отсутствуют некоторые детали, которые могли бы помочь дать лучший ответ. С учетом вышесказанного, надеюсь, это поможет вам.

Мои предположения:

  • Вы ищете периоды, когда запасных частей нет в наличии, и отметьте дату, когда они впервые былинет на складе и дата, когда они вернулись на склад
  • Я интерпретирую дату "на складе" как дату, когда у товара была запись, отмечающая, что его нет на складе. Например, деталь 1000 вышла из запаса 01.01.2009 и вернется в запас, начиная с 1/4/2019, по данным, а не 1/3/2019, как в примере
  • Еслитовара нет на складе, поэтому нам не нужна дата "на складе"

Я собираюсь поместить данные вашего примера во временную таблицу, чтобы немного облегчить жизньдемонстрируя:

with inventorydata(Part, StockDate, OutOfStock) as
(
  select 1000, '1/1/2019',1
  union 
  select 1000,'1/2/2019',1
  union 
  select 1000, '1/3/2019',1
  union
  select 1000, '1/4/2019',0
  union
  select 1000, '1/5/2019',1
  union 
  select 1005, '1/1/2019',0
  union 
  select 1005,'1/2/2019',1
  union 
  select 1005, '1/3/2019',1
  union
  select 1005, '1/4/2019',1
  union
  select 1005, '1/5/2019',0
)

Select Part,StockDate,OutOfStock 
INTO #Test
from inventorydata

Рассмотрим следующее:

SELECT 
    Part,
    StockDate,
    BackInStockDate
FROM
(
    SELECT 
        Part,
        StockDate,
        OutOfStock,
        LEAD(StockDate, 1) OVER (PARTITION BY Part ORDER BY StockDate) AS BackInStockDate
    FROM
    (
        SELECT 
            Part,
            StockDate,
            OutOfStock,
            LAG(OutOfStock, 1) OVER (PARTITION BY Part ORDER BY StockDate) AS PrevOutOfStock
        FROM #Test
    ) AS InnerData
    WHERE 
        OutOfStock <> PrevOutOfStock
        OR PrevOutOfStock IS NULL
) AS OuterData
WHERE
    OutOfStock = 1

Запрос InnerData извлекает каждую запись вместе со значением OutOfStock для предыдущей строки. Мы используем это, чтобы найти только те строки, которые представляют дату, когда статус акции изменился с наличия на складе до отсутствия на складе или наоборот. Это определяется по OutOfStock <> PrevOutOfStock и PrevOutOfStock IS NULL.

Когда у нас есть только строки, представляющие изменения, мы смотрим на строку next , чтобы получить дату, когда мы увидели состояние деталиизменение состояния, представленного в текущей строке. '

Наконец, мы отфильтровываем строки, где OutOfStock = 0, так как они представляют периоды на складе, которые мы игнорируем. Это дает нам следующий результат:

Part    StockDate   BackInStockDate
------- ----------- ----------------
1000    1/1/2019    1/4/2019
1000    1/5/2019    NULL
1005    1/2/2019    1/5/2019

Вы можете изменить структуру, чтобы получить другое значение BackInStockDate, если это не то значение, которое вам нужно, и добавить подсчет, чтобы получить то, что Occurances являетсядолжен быть.

...