使用 SQL 在 table 的每组记录中创建自定义记录。基于场景
Creating customised records in each group of records in table using SQL. Scenario based
Tab_X
**Col_1 Col_2 Col_3**
A1 B1 10
A1 B2 7
A2 B1 15
A2 B2 6
输出
**Col_1 Col_2 Col_3**
A1 B1 10
A1 B2 7
**A1 null 3 {10 - 7}**
A2 B1 15
A2 B2 6
**A2 Null 9 {15 - 6}**
Col_1 的所有组都应该有一条新记录 col_3 值如下
= Col_3 {其中 col_2 = ‘B1’} - SUM(Col_3) {其中 col_2 <> ‘B1’}
有人可以建议 SQL 实现这个吗?
with Tab_X (Col_1, Col_2, Col_3) as (
select 'A1', 'B1', 10 from dual union all
select 'A1', 'B2', 7 from dual union all
select 'A2', 'B1', 15 from dual union all
select 'A2', 'B2', 6 from dual
)
select *
from Tab_X
union all -- UPDATE, thanks @GordonLinoff
select Col_1
, null
, sum(Col_3 * case when Col_2 = 'B1' then 1 else -1 end)
from Tab_X
group by Col_1;
评论:
- 请在您的输入说明中使用 CTE(with 子句)以便回答更方便
- 请标记数据库供应商的问题。从
plsql
标签我猜你有 Oracle 不幸的是没有 filter (where)
子句,因此 sum (case when)
解决方法
- 也可以使用
group by rollup
解决,但我想不出来
更新:基于group by rollup
的解决方案
with Tab_X (Col_1, Col_2, Col_3) as (
select 'A1', 'B1', 10 from dual union all
select 'A1', 'B2', 7 from dual union all
select 'A2', 'B1', 15 from dual union all
select 'A2', 'B2', 6 from dual
)
select Col_1
, null
, case
when grouping(Col_2) = 1 then sum(Col_3 * case when Col_2 = 'B1' then 1 else -1 end)
else min(Col_3)
end as Col_3
from Tab_X
group by Col_1, rollup (Col_2)
我对前一行的 col_3 值使用了 "lag" 函数。
并且 "Rank" 列用于捕获更改 col_1 列(A1 到 A2)。当它更改时,排名会增加。
with tab_x (col_1, col_2, col_3)
as (select 'A1', 'B1', 10 from DUAL
union
select 'A1', 'B2', 7 from DUAL
union
select 'A2', 'B1', 15 from DUAL
union
select 'A2', 'B2', 6 from DUAL) select x.col_1, x.col_2, x.col_3
from (select col_1,
col_2,
col_3,
null RANK
from (select col_1,
null col_2,
LAG (col_3, 1, 0) over (order by col_1) - col_3
as col_3,
null,
RANK ()
over (partition by col_1 order by col_1, col_2)
RANK
from tab_x)
where RANK = 2
union all
select col_1,
col_2,
col_3,
null RANK
from tab_x
order by col_1, col_2) x order by col_1, col_2
Tab_X
**Col_1 Col_2 Col_3**
A1 B1 10
A1 B2 7
A2 B1 15
A2 B2 6
输出
**Col_1 Col_2 Col_3**
A1 B1 10
A1 B2 7
**A1 null 3 {10 - 7}**
A2 B1 15
A2 B2 6
**A2 Null 9 {15 - 6}**
Col_1 的所有组都应该有一条新记录 col_3 值如下 = Col_3 {其中 col_2 = ‘B1’} - SUM(Col_3) {其中 col_2 <> ‘B1’}
有人可以建议 SQL 实现这个吗?
with Tab_X (Col_1, Col_2, Col_3) as (
select 'A1', 'B1', 10 from dual union all
select 'A1', 'B2', 7 from dual union all
select 'A2', 'B1', 15 from dual union all
select 'A2', 'B2', 6 from dual
)
select *
from Tab_X
union all -- UPDATE, thanks @GordonLinoff
select Col_1
, null
, sum(Col_3 * case when Col_2 = 'B1' then 1 else -1 end)
from Tab_X
group by Col_1;
评论:
- 请在您的输入说明中使用 CTE(with 子句)以便回答更方便
- 请标记数据库供应商的问题。从
plsql
标签我猜你有 Oracle 不幸的是没有filter (where)
子句,因此sum (case when)
解决方法 - 也可以使用
group by rollup
解决,但我想不出来
更新:基于group by rollup
with Tab_X (Col_1, Col_2, Col_3) as (
select 'A1', 'B1', 10 from dual union all
select 'A1', 'B2', 7 from dual union all
select 'A2', 'B1', 15 from dual union all
select 'A2', 'B2', 6 from dual
)
select Col_1
, null
, case
when grouping(Col_2) = 1 then sum(Col_3 * case when Col_2 = 'B1' then 1 else -1 end)
else min(Col_3)
end as Col_3
from Tab_X
group by Col_1, rollup (Col_2)
我对前一行的 col_3 值使用了 "lag" 函数。 并且 "Rank" 列用于捕获更改 col_1 列(A1 到 A2)。当它更改时,排名会增加。
with tab_x (col_1, col_2, col_3)
as (select 'A1', 'B1', 10 from DUAL
union
select 'A1', 'B2', 7 from DUAL
union
select 'A2', 'B1', 15 from DUAL
union
select 'A2', 'B2', 6 from DUAL) select x.col_1, x.col_2, x.col_3
from (select col_1,
col_2,
col_3,
null RANK
from (select col_1,
null col_2,
LAG (col_3, 1, 0) over (order by col_1) - col_3
as col_3,
null,
RANK ()
over (partition by col_1 order by col_1, col_2)
RANK
from tab_x)
where RANK = 2
union all
select col_1,
col_2,
col_3,
null RANK
from tab_x
order by col_1, col_2) x order by col_1, col_2