Запрос для получения x количества строк на основе количества из другой таблицы - PullRequest
0 голосов
/ 18 января 2019

Редактировать: я использую SQL Server 2014

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

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

Пример:
Инвентарный стол

-------------------
| SKU  | Quantity |
-------------------
| 1234 | 10       |
-------------------

Таблица истории покупок

--------------------------------
| SKU  | Quantity | Date       |
--------------------------------
| 1234 | 5        | 2019-01-01 |
| 1234 | 3        | 2018-12-01 |
| 1234 | 9        | 2018-11-01 |
| 1234 | 4        | 2018-10-01 |
| 1234 | 12       | 2018-09-01 |
--------------------------------

Это результат, который я ожидаю

--------------------------------
| SKU  | Quantity | Date       |
--------------------------------
| 1234 | 5        | 2019-01-01 |
| 1234 | 3        | 2018-12-01 |
| 1234 | 9        | 2018-11-01 |
--------------------------------

Потому что 5 + 3 + 9 покрывает 10 у нас в наличии.

Может быть, я упускаю что-то простое, но я просто не могу придумать, как заставить результаты остановиться, в данном конкретном случае, на третьей записи.

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

Любая помощь будет принята с благодарностью, потому что я просто не могу обернуть голову вокруг этой.

Ответы [ 3 ]

0 голосов
/ 18 января 2019

Другой вариант - CROSS APPLY

* ** 1003 тысяча два * Пример
Select B.* 
 From  Inventory A
 Cross Apply ( 
               Select *
                From  (
                      Select *,RB = sum([Quantity]) over (Partition By SKU Order by Date Desc) - Quantity
                       From  Purchase 
                       Where SKU=A.SKU
                      ) B1
                Where RB<=A.Quantity 
              ) B
0 голосов
/ 18 января 2019

вы можете сделать это с помощью внутреннего соединения

при суммировании строк я использую IIF, чтобы установить текущую строку в ноль в сумме, потому что я не хочу включать это в проверку

begin try drop table #Phistory end try begin catch end catch;
begin try drop table #inventory  end try begin catch end catch;
SELECT 1234 SKU,5 Quantity, cast('20190101' as date) [date] into #Phistory;
INSERT #Phistory (SKU, Quantity,[date]) VALUES (1234,3,'20181201'), (1234,9,'20181101'),(1234,4,'20181001'),(1234,12,'20180901'),(1235,3,'20181201'), (1235,9,'20181101'),(1235,4,'20181001'),(1235,12,'20180901'),(1235,500,'20180801'),(1235,50,'20180601');
select  1234 SKU, 10 quantity into #inventory;
insert #inventory values(1235,99);

SELECT p1.SKU, 
        p1.Quantity, 
        p1.[Date],
        SUM(p2.quantity) RunningTotal
                FROM #Phistory p1 
                    JOIN #PHistory p2 
                        ON p1.SKU = p2.sku and p2.date >= p1.date
                        GROUP BY p1.SKU, 
                                p1.Quantity, 
                                p1.[Date]
                        HAVING SUM(IIF(p1.date = p2.date , 0 , p2.quantity)) 
                                 <= (SELECT inv.quantity from #inventory inv where inv.sku = p1.sku) 
                        order by p1.sku,p1.date DESC;
0 голосов
/ 18 января 2019

Я думаю, вы могли бы сделать что-то вроде следующего (не проверено):

SELECT ph.sku, ph.quantity, ph.date
FROM
(SELECT 
 purchasehistory.*, 
 SUM(quantity) OVER (PARTITION BY sku ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as tquantity
FROM purchasehistory) ph inner join inventory i
 on ph.sku = i.sku
WHERE
 ph.tquantity <= i.quantity

Идея в том, чтобы вычислить промежуточную сумму во внутреннем запросе, а затем объединить ее с таблицей инвентаризации. Я сделал предположение с датой ORDER BY, но вы можете изменить это.

Редактировать: Исходя из комментария, вам нужны первые N строк, которые используют весь ваш инвентарь (в отличие от первых N строк, которые не превышают ваш инвентарь). Я думаю, вы могли бы сделать что-то вроде:

SELECT ph.sku, ph.quantity, ph.date
FROM
(SELECT 
 purchasehistory.*, 
 SUM(quantity) OVER (PARTITION BY sku ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING) as tquantity
FROM purchasehistory) ph inner join inventory i
 on ph.sku = i.sku
WHERE
 ph.tquantity < i.quantity

Это та же основная идея, но промежуточная сумма переключается только на подсчет предыдущих строк (не включая текущую строку), и объединение использует <, а не <=. Таким образом, если количество предыдущих строк еще не составило инвентаризации, вы включите следующую строку (даже если эта сумма в настоящее время превышает запас). </p>

...