查询以从另一个表中获取基于数量的x行数

时间:2019-01-18 16:23:30

标签: sql-server sql-server-2014

编辑:我正在使用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 :(得分:1)

另一个选择是交叉申请

示例

 final ListAdapter adapter = new SimpleAdapter(
        MainActivity.this, 
        resultsdatalist,
        R.layout.list_item, 
        new String[]{"resultid", "result"}, 
        new int[]{R.id.resultid, R.id.result}) {
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = super.getView(position, convertView, parent);
        return view;
    }
};


lv.setAdapter(adapter);

答案 1 :(得分:0)

我认为您可能可以执行以下操作(未经测试):

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

这是相同的基本思想,但是运行总和被切换为仅对前一行进行计数(不包括当前行),并且联接使用<而不是<=。这样,如果前一行的数量尚未总计到库存中,则将包括下一行(即使该总数现在已超过库存)。

答案 2 :(得分:0)

您可以使用INNER JOIN来完成

在对行求和时,我使用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;