【发布时间】:2019-09-27 09:19:42
【问题描述】:
我想解决一个在我的 SQL 历史中多次出现的抽象问题。如果我们假设我们是一家销售公司并谈论我们想要销售的零件(产品),那么这个抽象问题可以更好地实现,因此在不同的日期需要不同的数量。 另一方面,我们有我们的“填充可能性”,例如来自不同日期和数量的库存、生产、采购的数量。
我想仅使用一个查询(无过程,无临时表)来满足按所需日期和可用日期排序的需求。
作为技术基础,您可以假设有两个表:
- NEED_TABLE,其中列出了多种需求、所需日期和数量。
- FILL_TABLE,其中列出了多个“填充”、可用日期和数量。
在我的例子中有两个需求:
- 需要 A:我们需要 2019 年 1 月 2 日,数量 4 中的部件号 123
- 需要 B:我们需要 2019 年 6 月 2 日第 2 件的零件编号 123
我们有两个不同数量的“填充物”:
- 填写 X:我们在采购订单中的第 2 个零件编号为 123,可于 2019 年 1 月 1 日供货
- 填写 Y:我们在采购订单中的第 4 个零件编号为 123,供货时间为 2019 年 6 月 1 日
结果应该是:
- 我需要 2019 年 1 月 2 日数量为 4 的零件编号 123(“需要 A”),由数量 2 中的采购订单(“填充 X”)和数量 2 中的另一个采购订单(“填充Y" - 部分)。
- 我需要 2019 年 6 月 2 日的部件号 123,数量为 2(“需要 B”),它由数量 2 的采购订单填充(“填充 Y” - 部分)。
SQL 查询:
with
NEED_TABLE
as
(select 'A' NEED_ID, 123 partno, to_date('01/02/2019', 'MM/DD/YYYY') DATE_NEEDED, 4 NEED_QTY from dual
union all
select 'B' NEED_ID, 123 partno, to_date('06/02/2019', 'MM/DD/YYYY') DATE_NEEDED, 2 NEED_QTY from dual),
FILL_TABLE
as
(select 'X' FILL_ID, 123 partno, to_date('01/01/2019', 'MM/DD/YYYY') DATE_AVAILABLE, 2 FILL_QTY from dual
union all
select 'Y' FILL_ID, 123 partno, to_date('06/01/2019', 'MM/DD/YYYY') DATE_AVAILABLE, 4 FILL_QTY from dual)
select NEED_TABLE.NEED_ID
, NEED_TABLE.PARTNO
, NEED_TABLE.DATE_NEEDED
, NEED_TABLE.NEED_QTY
, FILL_TABLE.FILL_ID
, FILL_TABLE.DATE_AVAILABLE
, FILL_TABLE.FILL_QTY
/* all following is wrong/incomplete */
, lag(need_QTY - fill_QTY, 1, need_QTY)
over(
partition by NEED_ID
order by DATE_NEEDED, DATE_AVAILABLE) REAL_NEED_QTY
, greatest(
lag(need_QTY - fill_QTY, 1, need_QTY)
over(
partition by NEED_ID
order by DATE_NEEDED, DATE_AVAILABLE)
- FILL_QTY
, 0) LEFT_NEED_QTY
, abs(
least(
lag(need_QTY - fill_QTY, 1, need_QTY)
over(
partition by NEED_ID
order by DATE_NEEDED, DATE_AVAILABLE)
- FILL_QTY
, 0)) LEFT_FILL_QTY
from NEED_TABLE, FILL_TABLE
order by DATE_NEEDED, DATE_AVAILABLE;
如果您检查该查询的结果,第一个 NEED_ID“A”似乎一切正常。但是当它继续使用 NEED_ID“B”时,它不记得在填充需求“A”时 FILL_ID X 和 Y 已经减少了。
我希望得到如下结果:
NEED_ID A is filled by FILL_ID X qty 2
NEED_ID A is filled by FILL_ID Y qty 2
(NEED_ID A is filled by FILL_ID X qty 0)
NEED_ID B is filled by FILL_ID Y qty 2
NEED_TABLE:
| NEED_ID | PARTNO | DATE_NEEDED | NEED_QTY |
|---------|--------|-------------|----------|
| A | 123 | 01/02/2019 | 4 |
| B | 123 | 06/02/2019 | 2 |
FILL_TABLE:
| FILL_ID | PARTNO | DATE_AVAILABLE | FILL_QTY |
|---------|--------|----------------|----------|
| X | 123 | 01/01/2019 | 2 |
| Y | 123 | 06/01/2019 | 4 |
预期的查询结果:
| NEED_ID | PARTNO | DATE_NEEDED | NEED_QTY | FILL_ID | DATE_AVAILABLE | FILL_QTY | ***REAL_FILL*** | "WHY?" |
|---------|--------|-------------|----------|---------|----------------|----------|-----------------|---------------------------------------------------------------------|
| A | 123 | 01/02/2019 | 4 | X | 01/01/2019 | 2 | 2 | A needs 4, gets partially filled by X by 2 |
| A | 123 | 01/02/2019 | 4 | Y | 06/01/2019 | 4 | 2 | A still needs 2, gets completely filled by Y by 2 |
| B | 123 | 06/02/2019 | 2 | X | 01/01/2019 | 2 | 0 | B needs 2, can't get filled by X, because A already used that qty |
| B | 123 | 06/02/2019 | 2 | Y | 06/01/2019 | 4 | 2 | B still needs 2, gets completely filled by remaining qty of Y, by 2 |
非常感谢任何帮助 - 谢谢!
【问题讨论】:
-
填充表和需要表之间没有连接条件;交叉连接真的是你想要的吗?此外,请编辑您的问题以提供两个表的示例数据,以及您希望从查询中看到的结果。
-
交叉连接旨在使示例尽可能简单。在我的真实查询中,我加入了所有合适的“填充”的需求。但问题是,我的需求只能通过 FILL_TABLE 中的一组部分数量来满足。
-
类似抽象问题的另一个例子是:我想从一个仓库中取出 2 次 10 件的零件,该仓库有几个箱子,每个箱子的数量为 5。为了满足我的第一个需求,我从第一个垃圾箱中取出 5 件,从第二个垃圾箱中取出 5 件。为了满足我的第二个需求,我从第三个垃圾箱中取出 5 件,从第四个垃圾箱中取出 5 件。我现在的方法是,用合适的“填充”来“交叉连接”所有需求,并使用窗口函数(或其他东西?)将每个“填充”(在这种情况下是仓库箱)的(部分)数量分配给我的需求,直到需求得到满足或填充为空。
标签: sql oracle window-functions