Выбор уникальных записей на основе даты действия, заканчивающейся датой прекращения - PullRequest
0 голосов
/ 24 апреля 2019

У меня есть интересная головоломка, и я использую SQL Server 2012 или SQL Server 2016 (очевидно, T-SQL).У меня есть список продуктов, каждый со своим кодом UPC.Эти продукты имеют дату прекращения, и код UPC перерабатывается в новый продукт после даты прекращения.Допустим, в таблице Item_UPCs есть следующее:

    Item Key | Item Desc |     UPC    | UPC Discontinue Date
      123456 | Shovel    | 0009595959 | 2018-04-01
      123456 | Shovel    | 0007878787 | NULL
      234567 | Rake      | 0009595959 | NULL

Как вы видите, у меня есть UPC, который перерабатывается в новый продукт.К сожалению, у меня нет даты вступления в силу для таблицы UPC элементов, но в таблице элементов я указываю, когда элемент был добавлен в систему.Но давайте проигнорируем это.

Вот что я хочу сделать:

  • Для каждой записи инвентаря до даты прекращения показывать уникальный UPC, связанный с этой датой.Инвентарная запись состоит из «Дата инвентаризации», «Стоимость покупки», «Количество покупки», «Описание товара» и «UPC товара».
  • После окончания даты прекращения с (например: это следующий день), начните показывать только действующий UPC.
  • Убедитесь, что дублирующихся данных не существует, и UPC действительно "привязаны" к каждой строке, независимо от того, какая дата находится вquery.

Вот пример таблицы данных инвентаризации:

Inv_Key | Trans_Date | Item_Key | Purch_Qty | Purch_Cost
    123 | 2018-05-12 |   123456 |     12.00 | 24.00
    108 | 2018-03-22 |   123456 |      8.00 | 16.00
    167 | 2018-07-03 |   234567 |     12.00 | 12.00

Пример запроса:

SELECT DISTINCT
     s.SiteID
    ,id.Item_Key
    ,iu.Item_Desc
    ,iu.Item_Department
    ,iu.Item_Category
    ,iu.Item_Subcategory
    ,iu.UPC
    ,iu.UPC_Discontinue_Date
    ,id.Trans_Date
    ,id.Purch_Cost
    ,id.Purch_Qty
FROM Inventory_Details id
INNER JOIN Item_UPCs iu ON iu.Item_Key = id.Item_Key
INNER JOIN Sites s ON s.Site_Key = id.Site_Key

Реальный запрос, который я имею, далекслишком долго, чтобы оставлять здесь сообщения.Он имеет три CTE и результирующий запрос.Это просто макет.Вот пример набора результатов:

Site_ID | Item_Key | Item_Desc | Item_Department | Item_Category |    UPC     | UPC_Discontinue Date | Trans_Date | Purch_Cost | Purch_Qty
   2457 |   123456 | Shovel    | Digging Tools   |       Shovels | 0009595959 | 2018-04-01           | 2018-03-22 |      16.00 |      8.00
   2457 |   123456 | Shovel    | Digging Tools   |       Shovels | 0007878787 | NULL                 | 2018-03-22 |      16.00 |      8.00
   2457 |   234567 | Rakes     | Garden Tools    |         Rakes | 0009595959 | NULL                 | 2018-07-03 |      12.00 |     12.00
   2457 |   123456 | Shovel    | Digging Tools   |       Shovels | 0007878787 | NULL                 | 2018-05-12 |      24.00 |     12.00

Кто-нибудь из вас знает, как я могу «назначить» UPC для определенного диапазона дат в моем запросе, а затем «назначить» обновленный UPC для элемента длякаждая последующая дата вступления в силу?

Большое спасибо!

1 Ответ

1 голос
/ 24 апреля 2019

Учитывая вашу текущую таблицу Item_UPC, вы можете сгенерировать эффективные даты начала из Даты прекращения, используя аналитическую функцию LAG:

With Effective_UPCs as (
  select [Item_Key]
       , [Item_Desc]
       , [UPC]
       , coalesce(lag([UPC_Discontinue_Date])
           over (partition by [Item_Key]
                     order by coalesce( [UPC_Discontinue_Date]
                                      , datefromparts(9999,12,31))
           ),
           lag([UPC_Discontinue_Date])
           over (partition by [UPC]
                     order by coalesce( [UPC_Discontinue_Date]
                                      , datefromparts(9999,12,31))
         )) [UPC_Start_Date]
       , [UPC_Discontinue_Date]
    from Item_UPCs i
)
select * from Effective_UPCs;

Что дает следующее Результаты :

| Item_Key | Item_Desc |        UPC | UPC_Start_Date | UPC_Discontinue_Date |
|----------|-----------|------------|----------------|----------------------|
|   123456 |    Shovel | 0007878787 |     2018-04-01 |               (null) |
|   123456 |    Shovel | 0009595959 |         (null) |           2018-04-01 |
|   234567 |      Rake | 0009595959 |     2018-04-01 |               (null) |

Эта функция создает полностью открытый конец интервала, в котором даты начала и окончания могут быть нулевыми, что указывает на то, что она действует в течение всего времени. Чтобы использовать это в своем запросе, просто укажите Effective_UPCs CTE вместо таблицы Item_UPCs и добавьте пару дополнительных предикатов, чтобы учесть даты вступления в силу:

SELECT DISTINCT
     s.SiteID
    ,id.Item_Key
    ,iu.Item_Desc
    ,iu.Item_Department
    ,iu.Item_Category
    ,iu.Item_Subcategory
    ,iu.UPC
    ,iu.UPC_Discontinue_Date
    ,id.Trans_Date
    ,id.Purch_Cost
    ,id.Purch_Qty
FROM Inventory_Details id
INNER JOIN Effective_UPCs iu 
   ON iu.Item_Key = id.Item_Key
  and (iu.UPC_Start_Date is null       or iu.UPC_Start_Date < id.Trans_Date)
  and (iu.UPC_Discontinue_Date is null or id.Trans_Date <= iu.UPC_Discontinue_Date)
INNER JOIN Sites s ON s.Site_Key = id.Site_Key

Обратите внимание, что в приведенном выше запросе используется частично открытый диапазон (UPC_Start_Date <</strong> trans_date <= </strong> UPC_Discontinue_Date вместо <= для обоих неравенств), что предотвращает возникновение транзакций точно в день прекращения при сопоставлении как предыдущей, так и следующей <code>Item_Key записи. Если транзакции, которые происходят точно в день прекращения, должны соответствовать новой записи, а не старой, просто поменяйте местами два неравенства:

  and (iu.UPC_Start_Date is null       or iu.UPC_Start_Date <= id.Trans_Date)
  and (iu.UPC_Discontinue_Date is null or id.Trans_Date < iu.UPC_Discontinue_Date)

вместо

  and (iu.UPC_Start_Date is null       or iu.UPC_Start_Date < id.Trans_Date)
  and (iu.UPC_Discontinue_Date is null or id.Trans_Date <= iu.UPC_Discontinue_Date)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...