我有一个挑战,我必须建立一些查询,我对如何开始有点迷失。我想我可能需要使用分区来实现这一点,但不确定他们的方式。 如果有人可以与我分享知识,请在此处发帖:)
首先抱歉让人感到困惑,但老实说不知道怎么用一行描述:(
问题是我有两张桌子:
广告
ITEM QTY PRIORITY
-----------------------------
ITEM1 10 1
ITEM1 5 2
ITEM1 4 3
ITEM1 7 4
ITEM2 4 1
ITEM2 19 2
LIST
ITEM QTY
-----------------
ITEM1 17
ITEM2 13
我需要实现的逻辑是表LIST从INVENTORY表中删除了数量。但它必须按项目执行并删除优先级中的数量。 例如:
在LIST表中,我们有ITEM1 = 17 这意味着我们需要按照优先顺序删除Inventory表中的这个数量。
因此ITEM1的结果如下:
ITEM QTY PRIORITY
-----------------------------
ITEM1 0 1
ITEM1 0 2
ITEM1 2 3
ITEM1 7 4
如果将整个逻辑应用于所有项目,则生成的查询应返回如下内容:
ITEM QTY PRIORITY
-----------------------------
ITEM1 0 1
ITEM1 0 2
ITEM1 2 3
ITEM1 7 4
ITEM2 0 1
ITEM2 10 2
任何人都知道如何处理这个问题?
答案 0 :(得分:5)
Oracle安装程序:
CREATE TABLE inventory ( item, qty, priority ) AS
SELECT 'ITEM1', 10, 1 FROM DUAL UNION ALL
SELECT 'ITEM1', 5, 2 FROM DUAL UNION ALL
SELECT 'ITEM1', 4, 3 FROM DUAL UNION ALL
SELECT 'ITEM1', 7, 4 FROM DUAL UNION ALL
SELECT 'ITEM2', 4, 1 FROM DUAL UNION ALL
SELECT 'ITEM2', 19, 2 FROM DUAL;
CREATE TABLE list ( item, qty ) AS
SELECT 'ITEM1', 17 FROM DUAL UNION ALL
SELECT 'ITEM2', 13 FROM DUAL;
<强>查询强>:
MERGE INTO inventory dst
USING (
SELECT i.item,
LEAST(
GREATEST(
SUM( i.qty ) OVER ( PARTITION BY i.item ORDER BY i.priority )
- COALESCE( l.qty, 0 ),
0
),
i.qty
) AS qty,
i.priority
FROM inventory i
LEFT OUTER JOIN
list l
ON ( i.item = l.item )
) src
ON ( src.item = dst.item AND src.priority = dst.priority )
WHEN MATCHED THEN
UPDATE SET qty = src.qty;
<强>输出强>:
SELECT * FROM inventory;
ITEM QTY PRIORITY
----- --- --------
ITEM1 0 1
ITEM1 0 2
ITEM1 2 3
ITEM1 7 4
ITEM2 0 1
ITEM2 10 2
答案 1 :(得分:2)
这可以通过明智地使用分析函数来计算运行总和,并将剩余的数量从上一行中删除来解决,如下所示:
WITH inventory AS (SELECT 'ITEM1' item, 10 qty, 1 priority FROM dual UNION ALL
SELECT 'ITEM1' item, 5 qty, 2 priority FROM dual UNION ALL
SELECT 'ITEM1' item, 4 qty, 3 priority FROM dual UNION ALL
SELECT 'ITEM1' item, 7 qty, 4 priority FROM dual UNION ALL
SELECT 'ITEM2' item, 4 qty, 1 priority FROM dual UNION ALL
SELECT 'ITEM2' item, 19 qty, 2 priority FROM dual),
LIST AS (SELECT 'ITEM1' item, 17 qty FROM dual UNION ALL
SELECT 'ITEM2' item, 13 qty FROM dual),
-- end of mimicking your two tables; you would not need to do the above
-- see below for the main query
interim_res AS (SELECT inv.item,
inv.qty,
inv.priority,
l.qty qty_to_del,
l.qty - SUM(inv.qty) OVER (PARTITION BY inv.item ORDER BY inv.priority) qty_left_to_del
FROM inventory inv
INNER JOIN LIST l ON inv.item = l.item),
final_res AS (SELECT item,
qty,
priority,
qty_to_del,
qty_left_to_del,
LAG(qty_left_to_del, 1, qty_to_del) OVER (PARTITION BY item ORDER BY priority) qty_to_del_from_current_qty
FROM interim_res)
SELECT item,
qty old_qty,
CASE WHEN qty_to_del_from_current_qty >= qty
THEN 0
WHEN qty_to_del_from_current_qty > 0
THEN qty - qty_to_del_from_current_qty
ELSE qty
END new_qty,
priority
FROM final_res;
ITEM OLD_QTY NEW_QTY PRIORITY
----- ---------- ---------- ----------
ITEM1 10 0 1
ITEM1 5 0 2
ITEM1 4 2 3
ITEM1 7 7 4
ITEM2 4 0 1
ITEM2 19 10 2
为了解决您的问题,首先我在库存表中,在每个项目和优先级顺序中创建了数量的运行总和。然后我们可以使用它从items表中的qty中删除,以找出我们剩下多少从下一个qty中删除(忽略我们可以得到负值的事实)。
一旦我们有了这个,接下来我们需要将要删除的数量与前一行相关联 - 我们使用LAG()来执行此操作 - 对于第一行,我们将其默认为完整的items.qty(这就是第三个参数的含义。)
(注意我把这个计算放在一个单独的子查询中,这样我们就不必在整个地方重复LAG()函数;我们可以将它称为最终外部查询中的列别名。你可以将final_res子查询和外部查询合并为一个,如果你不介意拥有所有的LAG()!)
一旦我们知道要从items.qty中删除的值,我们知道我们要采取以下三种行动之一:
最后,要更新你的表,我会使用MERGE。假设在库存表中,(item,priority)是唯一键,以下应该起作用:
MERGE INTO items tgt
USING (WITH interim_res AS (SELECT inv.item,
inv.qty,
inv.priority,
l.qty qty_to_del,
l.qty - SUM(inv.qty) OVER (PARTITION BY inv.item ORDER BY inv.priority) qty_left_to_del
FROM inventory inv
INNER JOIN LIST l ON inv.item = l.item),
final_res AS (SELECT item,
qty,
priority,
qty_to_del,
qty_left_to_del,
LAG(qty_left_to_del, 1, qty_to_del) OVER (PARTITION BY item ORDER BY priority) qty_to_del_from_current_qty
FROM interim_res)
SELECT item,
qty old_qty,
CASE WHEN qty_to_del_from_current_qty >= qty
THEN 0
WHEN qty_to_del_from_current_qty > 0
THEN qty - qty_to_del_from_current_qty
ELSE qty
END new_qty,
priority
FROM final_res) src
ON (tgt.item = src.item AND tgt.priority = src.priority)
WHEN MATCHED THEN
UPDATE SET tgt.qty = src.new_qty
WHERE tgt.qty != src.new_qty;
答案 2 :(得分:1)