我有一个数据集:
SELECT '1' ID, '30' CurrQty, '100' ReqQty FROM dual
UNION ALL SELECT '1' ID, '30' CurrQty, '100' ReqQty FROM dual
UNION ALL SELECT '1' ID, '20' CurrQty, '100' ReqQty FROM dual
UNION ALL SELECT '2' ID, '100' CurrQty, '100' ReqQty FROM dual
ID CURRQTY REQQTY
-- ------- ------
1 30 100
1 30 100
1 20 100
2 100 100
我想得到这样的东西:
ID | CurrQty | ReqQty
1 | 30 | 100
1 | 30 | 100
1 | 20 | 100
1 | 20 | 100 - created a new line ReqQty - Sum(CurrQty)
2 | 100 | 100
如果同一Sum(CurrQty)
的{{1}}小于Id
,则用不同的ReqQty
创建新行。
我尝试过类似的操作,但是它为每一行创建了一个重复行,并且我只想在ReqQty - Sum(CurrQty)
组内创建一条新行:
Id
答案 0 :(得分:1)
您可以分两个阶段执行此操作。首先,您可以使用解析求和函数来查看是否满足要求:
-- CTE for sample data
with your_table (id, currqty, reqqty) as (
select 1, 30, 100 from dual
union all select 1, 30, 100 from dual
union all select 1, 20, 100 from dual
union all select 2, 100, 100 from dual
)
-- actual query
select id, currqty, reqqty,
sum(currqty) over (partition by id) as totalqty
from your_table;
ID CURRQTY REQQTY TOTALQTY
-- ---------- ---------- ----------
1 30 100 80
1 30 100 80
1 20 100 80
2 100 100 100
然后将其用作CTE,添加第二个分析函数以为每个ID选择任何行以用作额外ID的基础(在需要时),并将两个查询合并在一起:
with your_table (id, currqty, reqqty) as (
select 1, 30, 100 from dual
union all select 1, 30, 100 from dual
union all select 1, 20, 100 from dual
union all select 2, 100, 100 from dual
),
cte (id, currqty, reqqty, totalqty, rn) as (
select id, currqty, reqqty,
sum(currqty) over (partition by id),
row_number() over (partition by id order by null)
from your_table
)
select id, currqty, reqqty
from cte
union all
select id, reqqty - totalqty, reqqty
from cte
where totalqty < reqqty
and rn = 1;
ID CURRQTY REQQTY
-- ---------- ----------
1 30 100
1 30 100
1 20 100
2 100 100
1 20 100
联合的第一个分支只是通过CTE获取您的原始数据。第二个分支只为总数不符合要求的任何ID查找一行,并为该ID生成一个新行以弥补差异。
如果您不想使用第二个分析函数,则可以使用distinct
查询:
...
select id, currqty, reqqty
from cte
union all
select distinct id, reqqty - totalqty, reqqty
from cte
where totalqty < reqqty;
顺便说一句,我假设您的值实际上都是数字,而不是字符串。存储数量或数字ID或任何其他数字值,因为字符串没有多大意义。
答案 1 :(得分:1)
奇怪的是,在输出中您没有标记出“添加的”行-在报告或后续处理中,如何将它们与原始行区分开?
无论如何,这与我无关。然后:为什么数量是字符串而不是数字?那真的没有道理;在模拟数据中,我对此进行了更改。
您没有说当reqqty
小于currqty
之和时想要发生什么,也没有说应该如何处理任何可能的null
。我假设没有null
,如果reqqty
小于currqty
的总和,则您不希望为该客户做任何事情(除了输出原始行)。
给定客户的所有行中的reqqty
是否相同?这是您的问题唯一有道理的方法;但是,如果您显示的是基表(而不是某些联接的结果),则您的表将违反“第三范式”。您可能需要考虑一下。
这是一种非常简单快捷的方法来完成您需要的操作。我没有订购输出,因为您对此没有多说。
with
dataset(id, currqty, reqqty) as (
select '1', 30, 100 from dual union all
select '1', 30, 100 from dual union all
select '1', 20, 100 from dual union all
select '2', 100, 100 from dual
)
select id, currqty, reqqty
from dataset
union all
select id, min(reqqty) - sum(currqty) as currqty, min(reqqty) as reqqty
from dataset
group by id
having sum(currqty) < min(reqqty)
-- ORDER BY <whatever>; ORDER BY applies to the result of UNION ALL.
;
ID CURRQTY REQQTY
-- ---------- ----------
1 30 100
1 30 100
1 20 100
2 100 100
1 20 100