Строка SQL-запроса должна уменьшаться от итога группы, пока значение не станет равным нулю или новой группе - PullRequest
0 голосов
/ 22 октября 2019

У меня есть следующие две таблицы:

Таблица сведений о заказе

| OrderId | OrderDetailId | ItemId | QtyOrdered | DateNeeded |
--------------------------------------------------------------
| 16669   | 36915         | 139    | 10         | 2019-10-21 |
| 16669   | 36916         | 139    | 15         | 2019-11-21 |
| 16670   | 36917         | 11     | 1          | 2019-10-21 |
| 16673   | 36922         | 250    | 5          | 2019-10-11 |
| 16673   | 36923         | 139    | 10         | 2019-10-11 |

и Таблица распределения заказов

| OrderId | ItemId | ItemLot | QtyAllocated |
---------------------------------------------
| 16669   | 139    | 2345678 | 2            |
| 16669   | 139    | 2256245 | 3            |
| 16669   | 139    | 2356245 | 10           |
| 16673   | 139    | 2356245 | 8            |
| 16673   | 139    | 2245689 | 2            |
| 16673   | 250    | 2019001 | 5            |

Вот сценарий: Заказ 16669 имеетдве строки на нем, но для одного и того же товара и разных количествах с разными датами поставки. Заказ 16670 имеет одну строку, а 16673 - две строки с разными пунктами. Мне нужно иметь возможность сообщать детали заказа с соответствующими выделенными или неупорядоченными количествами.

Из второй таблицы видно, что у Order 16669 в общей сложности 15 единиц, выделенных для ItemId 139. Мне нужно сообщить об этом как 10 единиц, выделенных для OrderDetailId 36915 (мы хотим показать эту строку как полностью выделенную, посколькунеобходимая дата раньше, чем OrderDetailId 36916). Не существует прямой связи между таблицей размещения и Order Order только через OrderId.

Вот пример того, что мне нужно построить с помощью запроса, но я не смог выяснить:

| OrderId | DetailId | ItemId | OrderQty | TotalAlloc | AllocQty | BackorderQty|
--------------------------------------------------------------------------------
| 16669   | 36915    | 139    | 10       | 15         | 10       | 0           |
| 16669   | 36916    | 139    | 15       | 15         | 5        | 10          |
| 16670   | 36917    | 11     | 1        | 0          | 0        | 1           |
| 16673   | 36922    | 250    | 5        | 5          | 5        | 0           |
| 16673   | 36923    | 139    | 10       | 10         | 10       | 0           |

Для заказа 16669 было выделено 15 единиц. Строка № 1 требует 10 из этих единиц, оставляя 5 единиц для следующей строки (ей) и 0 кол-во заказов. Строка 2 требует 15 единиц, поэтому мы берем оставшиеся 5 единиц и показываем количество промежуточного заказа 10. Строка 3 начинает новый ордер (или может быть того же порядка, но другого предмета), поэтому мы сбрасываем.

Я довольноуверен, что ответ - это какой-то вариант запроса SUM OVER, но не смог его получить.

Может ли кто-нибудь помочь мне найти решение?

1 Ответ

0 голосов
/ 01 ноября 2019

Я почти уверен, что ответ - это некий вариант запроса SUM OVER.

Вы правы. Вы можете поиграть с Rows-Range thing, чтобы попасть туда.

Попробуйте этот сценарий,

CREATE TABLE #Order(OrderId int,OrderDetailId int, ItemId int, QtyOrdered int,  DateNeeded date)
insert into #Order values
 (16669  , 36915, 139, 10 ,'2019-10-21'),(16669  , 36916, 139, 15 ,'2019-11-21')
,(16670  , 36917, 11 , 1  ,'2019-10-21'),(16673  , 36922, 250, 5  ,'2019-10-11')
,(16673  , 36923, 139, 10 ,'2019-10-11')


CREATE TABLE #OrderAllocation (OrderId int, ItemId int, ItemLot bigint,  QtyAllocated int)
insert into #OrderAllocation values
 (16669,139,2345678, 2 ),(16669, 139,2256245,3)
,(16669,139,2356245, 10),(16673, 139,2356245,8)
,(16673,139,2245689, 2),(16673, 250,2019001,5);

WITH CTE
     AS (SELECT OrderId,
                ItemId,
                SUM(QtyAllocated) TotalAlloc
         FROM #OrderAllocation
         GROUP BY OrderId,
                  ItemId),
     CTE1
     AS (SELECT o.OrderId,
                o.OrderDetailId AS DetailId,
                o.ItemId,
                o.QtyOrdered AS OrderQty,
                ISNULL(TotalAlloc, 0) TotalAlloc,
                SUM(QtyOrdered) OVER(PARTITION BY o.OrderId,
                                                  o.ItemId
                ORDER BY o.dateneeded ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) RunningAllocQty,
                DateNeeded
         FROM #Order O
              LEFT JOIN CTE C ON o.OrderId = c.orderid
                                 AND o.ItemId = c.ItemId)
     SELECT OrderId,
            DetailId,
            ItemId,
            OrderQty,
            TotalAlloc,
            CASE
                WHEN TotalAlloc > 0
                THEN OrderQty - ISNULL(RunningAllocQty, 0)
                ELSE 0
            END AllocQty,
            CASE
                WHEN TotalAlloc > 0
                THEN OrderQty - (OrderQty - ISNULL(RunningAllocQty, 0))
                ELSE OrderQty
            END BackOrderQty
     FROM CTE1;

drop table #Order,#OrderAllocation

В этом сценарии вы можете исправить join condition, если он неверен.

Запрос может быть оптимизирован после ознакомления с данными. В этих небольших выборочных данных так много сомнений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...