如何将三个 select 查询合并为一个以在 Oracle 中实现如下所示的预期结果?
How to merge three select queries into one in order to achieve the desired result as below in Oracle?
目的是在每个项目的计划增量和实际增量第一次出现负值时推送 'N' 标志。
'Y' 标志应推入所有其余行。
Rank列定义顺序,Project ID定义一个项目的数据。
只能使用 select 个查询
使用下面的table结构
'''
CREATE TABLE payBackTable (projectID varchar2(10), quarterYear varchar2(10), Rank int, planned_delta int, actual_delta int )
INSERT INTO payBackTable values
( 'P001','Q1-2017', 1, 2000, 900)
( 'P001','Q2-2017', 2, 18000, 800)
( 'P001','Q3-2017', 3, 0, 7000)
( 'P001','Q4-2017', 4, 9000, -90)
( 'P001','Q1-2018', 5, -10, 9000)
( 'P001','Q2-2018', 6, 100, 70)
( 'P001','Q3-2018', 7, -90, -900)
( 'P001','Q4-2018', 8, 200, -8)
( 'P002', 'Q3-2016', 1, 1000, 90 )
( 'P002', 'Q4-2016', 2, -200, 90 )
( 'P002', 'Q1-2017', 3, 4000, -500 )
( 'P002', 'Q2-2017', 4, 10, -90 )
( 'P003', 'Q3-2021', 1, -10, 700 )
( 'P003', 'Q4-2021', 2, 100, -800 )
( 'P003', 'Q1-2022', 3, -100, -900 )
( 'P003', 'Q2-2022', 3, -90, 100 )
'''
来源Table
项目编号
季度
排名
计划增量
实际增量
P001
2017 年第一季度
1
2000
900
P001
2017 年第 2 季度
2
18000
800
P001
2017 年第 3 季度
3
0
7000
P001
2017 年第四季度
4
9000
-90
P001
2018 年第一季度
5
-10
9000
P001
2018 年第二季度
6
100
70
P001
2018 年第 3 季度
7
-90
-900
P001
2018 年第四季度
8
200
-8
P002
2016 年第 3 季度
1
1000
90
P002
2016 年第四季度
2
-200
90
P002
2017 年第一季度
3
4000
-500
P002
2017 年第 2 季度
4
10
-90
P003
2021 年第 3 季度
1
-10
700
P003
2021 年第 4 季度
2
100
-800
P003
2022 年第一季度
3
-100
-900
P003
2022 年第二季度
4
-90
100
想要的结果
项目编号
季度
排名
计划增量
实际增量
计划中的标志
实际标志
P001
2017 年第一季度
1
2000
900
Y
Y
P001
2017 年第 2 季度
2
18000
800
Y
Y
P001
2017 年第 3 季度
3
0
7000
Y
Y
P001
2017 年第四季度
4
9000
-90
Y
N
P001
2018 年第一季度
5
-10
9000
N
Y
P001
2018 年第二季度
6
100
70
Y
Y
P001
2018 年第 3 季度
7
-90
-900
Y
Y
P001
2018 年第四季度
8
200
-8
Y
Y
P002
2016 年第 3 季度
1
1000
90
Y
Y
P002
2016 年第四季度
2
-200
90
N
Y
P002
2017 年第一季度
3
4000
-500
Y
N
P002
2017 年第 2 季度
4
10
-90
Y
Y
P003
2021 年第 3 季度
1
-10
700
N
Y
P003
2021 年第 4 季度
2
100
-800
Y
N
P003
2022 年第一季度
3
-100
-900
Y
Y
P003
2022 年第二季度
4
-90
100
Y
Y
我已经能够 table 使用三个不同的 queries/batch 作业来推送所需的结果,但不确定如何在单个 query/batch 作业中实现它。
在 Planned Flag
中推送 'N' flag
select projectID,quarterYear, 'N' from(
select projectID, quarterYear,
Row_number() OVER(PARTITION BY projectID ORDER BY to_number(Rank))
as rownumm from payBackTable
where to_number(planned_delta) < 0) where rownumm = 1
将 'N' 标志推入 Actual Flag
select projectID,quarterYear, 'N' from(
select projectID, quarterYear,
Row_number() OVER(PARTITION BY projectID ORDER BY to_number(Rank))
as rownumm from payBackTable
where to_number(actual_delta) < 0) where rownumm = 1
在Planned Flag和Actual Flag中推送'Y' flag
select projectID,
quarterYear,
case planned_Flag when NULL then 'Y' ELSE planned_Flag END,
case actual_Flag when NULL then 'Y' ELSE actual_Flag END
from payBackTable
您可以根据每个值的符号获得项目中每个值的排名和:
select projectid, quarteryear, rank, planned_delta, actual_delta,
dense_rank() over (partition by projectid, sign(planned_delta) order by rank) as flag1,
dense_rank() over (partition by projectid, sign(actual_delta) order by rank) as flag2
from paybacktable
order by projectid, rank
PROJECTID
QUARTERYEAR
RANK
PLANNED_DELTA
ACTUAL_DELTA
FLAG1
FLAG2
P001
Q1-2017
1
2000
900
1
1
P001
Q2-2017
2
18000
800
2
2
P001
Q3-2017
3
0
7000
1
3
P001
Q4-2017
4
9000
-90
3
1
P001
Q1-2018
5
-10
9000
1
4
P001
Q2-2018
6
100
70
4
5
P001
Q3-2018
7
-90
-900
2
2
P001
Q4-2018
8
200
-8
5
3
...
然后将它们用作 case 表达式的一部分;如果排名 i1 和 的值为负数,那么它是第一个负值:
select projectid, quarteryear, rank, planned_delta, actual_delta,
case
when sign(planned_delta) = -1
and dense_rank() over (partition by projectid, sign(planned_delta) order by rank) = 1
then 'N'
else 'Y'
end as planned_flag,
case
when sign(actual_delta) = -1
and dense_rank() over (partition by projectid, sign(actual_delta) order by rank) = 1
then 'N'
else 'Y'
end as actual_flag
from paybacktable
order by projectid, rank
PROJECTID
QUARTERYEAR
RANK
PLANNED_DELTA
ACTUAL_DELTA
PLANNED_FLAG
ACTUAL_FLAG
P001
Q1-2017
1
2000
900
Y
Y
P001
Q2-2017
2
18000
800
Y
Y
P001
Q3-2017
3
0
7000
Y
Y
P001
Q4-2017
4
9000
-90
Y
N
P001
Q1-2018
5
-10
9000
N
Y
P001
Q2-2018
6
100
70
Y
Y
P001
Q3-2018
7
-90
-900
Y
Y
P001
Q4-2018
8
200
-8
Y
Y
P002
Q3-2016
1
1000
90
Y
Y
P002
Q4-2016
2
-200
90
N
Y
P002
Q1-2017
3
4000
-500
Y
N
P002
Q2-2017
4
10
-90
Y
Y
P003
Q3-2021
1
-10
700
N
Y
P003
Q4-2021
2
100
-800
Y
N
P003
Q2-2022
3
-90
100
Y
Y
P003
Q1-2022
3
-100
-900
Y
Y
select P1.projectID, P1.quarterYear, P1.Rank, P1.planned_Delta, P1.actual_Delta,
case when Rank = X1.RankMin then 'N' ELSE 'Y' END plannedFlag ,
case when Rank = X2.RankMin then 'N' ELSE 'Y' END actualFlag
from payBackTable P1
left join (
select projectID, min(Rank) RankMin
from payBackTable P2
where Planned_Delta < 0
group by projectID
) X1 on P1.projectID = X1.projectID
left join (
select projectID, min(Rank) RankMin
from payBackTable P2
where Actual_Delta < 0
group by projectID
) X2 on P1.projectID = X2.projectID
目的是在每个项目的计划增量和实际增量第一次出现负值时推送 'N' 标志。 'Y' 标志应推入所有其余行。 Rank列定义顺序,Project ID定义一个项目的数据。
只能使用 select 个查询
使用下面的table结构 '''
CREATE TABLE payBackTable (projectID varchar2(10), quarterYear varchar2(10), Rank int, planned_delta int, actual_delta int )
INSERT INTO payBackTable values
( 'P001','Q1-2017', 1, 2000, 900)
( 'P001','Q2-2017', 2, 18000, 800)
( 'P001','Q3-2017', 3, 0, 7000)
( 'P001','Q4-2017', 4, 9000, -90)
( 'P001','Q1-2018', 5, -10, 9000)
( 'P001','Q2-2018', 6, 100, 70)
( 'P001','Q3-2018', 7, -90, -900)
( 'P001','Q4-2018', 8, 200, -8)
( 'P002', 'Q3-2016', 1, 1000, 90 )
( 'P002', 'Q4-2016', 2, -200, 90 )
( 'P002', 'Q1-2017', 3, 4000, -500 )
( 'P002', 'Q2-2017', 4, 10, -90 )
( 'P003', 'Q3-2021', 1, -10, 700 )
( 'P003', 'Q4-2021', 2, 100, -800 )
( 'P003', 'Q1-2022', 3, -100, -900 )
( 'P003', 'Q2-2022', 3, -90, 100 )
'''
来源Table
项目编号 | 季度 | 排名 | 计划增量 | 实际增量 |
---|---|---|---|---|
P001 | 2017 年第一季度 | 1 | 2000 | 900 |
P001 | 2017 年第 2 季度 | 2 | 18000 | 800 |
P001 | 2017 年第 3 季度 | 3 | 0 | 7000 |
P001 | 2017 年第四季度 | 4 | 9000 | -90 |
P001 | 2018 年第一季度 | 5 | -10 | 9000 |
P001 | 2018 年第二季度 | 6 | 100 | 70 |
P001 | 2018 年第 3 季度 | 7 | -90 | -900 |
P001 | 2018 年第四季度 | 8 | 200 | -8 |
P002 | 2016 年第 3 季度 | 1 | 1000 | 90 |
P002 | 2016 年第四季度 | 2 | -200 | 90 |
P002 | 2017 年第一季度 | 3 | 4000 | -500 |
P002 | 2017 年第 2 季度 | 4 | 10 | -90 |
P003 | 2021 年第 3 季度 | 1 | -10 | 700 |
P003 | 2021 年第 4 季度 | 2 | 100 | -800 |
P003 | 2022 年第一季度 | 3 | -100 | -900 |
P003 | 2022 年第二季度 | 4 | -90 | 100 |
想要的结果
项目编号 | 季度 | 排名 | 计划增量 | 实际增量 | 计划中的标志 | 实际标志 |
---|---|---|---|---|---|---|
P001 | 2017 年第一季度 | 1 | 2000 | 900 | Y | Y |
P001 | 2017 年第 2 季度 | 2 | 18000 | 800 | Y | Y |
P001 | 2017 年第 3 季度 | 3 | 0 | 7000 | Y | Y |
P001 | 2017 年第四季度 | 4 | 9000 | -90 | Y | N |
P001 | 2018 年第一季度 | 5 | -10 | 9000 | N | Y |
P001 | 2018 年第二季度 | 6 | 100 | 70 | Y | Y |
P001 | 2018 年第 3 季度 | 7 | -90 | -900 | Y | Y |
P001 | 2018 年第四季度 | 8 | 200 | -8 | Y | Y |
P002 | 2016 年第 3 季度 | 1 | 1000 | 90 | Y | Y |
P002 | 2016 年第四季度 | 2 | -200 | 90 | N | Y |
P002 | 2017 年第一季度 | 3 | 4000 | -500 | Y | N |
P002 | 2017 年第 2 季度 | 4 | 10 | -90 | Y | Y |
P003 | 2021 年第 3 季度 | 1 | -10 | 700 | N | Y |
P003 | 2021 年第 4 季度 | 2 | 100 | -800 | Y | N |
P003 | 2022 年第一季度 | 3 | -100 | -900 | Y | Y |
P003 | 2022 年第二季度 | 4 | -90 | 100 | Y | Y |
我已经能够 table 使用三个不同的 queries/batch 作业来推送所需的结果,但不确定如何在单个 query/batch 作业中实现它。 在 Planned Flag
中推送 'N' flagselect projectID,quarterYear, 'N' from(
select projectID, quarterYear,
Row_number() OVER(PARTITION BY projectID ORDER BY to_number(Rank))
as rownumm from payBackTable
where to_number(planned_delta) < 0) where rownumm = 1
将 'N' 标志推入 Actual Flag
select projectID,quarterYear, 'N' from(
select projectID, quarterYear,
Row_number() OVER(PARTITION BY projectID ORDER BY to_number(Rank))
as rownumm from payBackTable
where to_number(actual_delta) < 0) where rownumm = 1
在Planned Flag和Actual Flag中推送'Y' flag
select projectID,
quarterYear,
case planned_Flag when NULL then 'Y' ELSE planned_Flag END,
case actual_Flag when NULL then 'Y' ELSE actual_Flag END
from payBackTable
您可以根据每个值的符号获得项目中每个值的排名和:
select projectid, quarteryear, rank, planned_delta, actual_delta,
dense_rank() over (partition by projectid, sign(planned_delta) order by rank) as flag1,
dense_rank() over (partition by projectid, sign(actual_delta) order by rank) as flag2
from paybacktable
order by projectid, rank
PROJECTID | QUARTERYEAR | RANK | PLANNED_DELTA | ACTUAL_DELTA | FLAG1 | FLAG2 |
---|---|---|---|---|---|---|
P001 | Q1-2017 | 1 | 2000 | 900 | 1 | 1 |
P001 | Q2-2017 | 2 | 18000 | 800 | 2 | 2 |
P001 | Q3-2017 | 3 | 0 | 7000 | 1 | 3 |
P001 | Q4-2017 | 4 | 9000 | -90 | 3 | 1 |
P001 | Q1-2018 | 5 | -10 | 9000 | 1 | 4 |
P001 | Q2-2018 | 6 | 100 | 70 | 4 | 5 |
P001 | Q3-2018 | 7 | -90 | -900 | 2 | 2 |
P001 | Q4-2018 | 8 | 200 | -8 | 5 | 3 |
...
然后将它们用作 case 表达式的一部分;如果排名 i1 和 的值为负数,那么它是第一个负值:
select projectid, quarteryear, rank, planned_delta, actual_delta,
case
when sign(planned_delta) = -1
and dense_rank() over (partition by projectid, sign(planned_delta) order by rank) = 1
then 'N'
else 'Y'
end as planned_flag,
case
when sign(actual_delta) = -1
and dense_rank() over (partition by projectid, sign(actual_delta) order by rank) = 1
then 'N'
else 'Y'
end as actual_flag
from paybacktable
order by projectid, rank
PROJECTID | QUARTERYEAR | RANK | PLANNED_DELTA | ACTUAL_DELTA | PLANNED_FLAG | ACTUAL_FLAG |
---|---|---|---|---|---|---|
P001 | Q1-2017 | 1 | 2000 | 900 | Y | Y |
P001 | Q2-2017 | 2 | 18000 | 800 | Y | Y |
P001 | Q3-2017 | 3 | 0 | 7000 | Y | Y |
P001 | Q4-2017 | 4 | 9000 | -90 | Y | N |
P001 | Q1-2018 | 5 | -10 | 9000 | N | Y |
P001 | Q2-2018 | 6 | 100 | 70 | Y | Y |
P001 | Q3-2018 | 7 | -90 | -900 | Y | Y |
P001 | Q4-2018 | 8 | 200 | -8 | Y | Y |
P002 | Q3-2016 | 1 | 1000 | 90 | Y | Y |
P002 | Q4-2016 | 2 | -200 | 90 | N | Y |
P002 | Q1-2017 | 3 | 4000 | -500 | Y | N |
P002 | Q2-2017 | 4 | 10 | -90 | Y | Y |
P003 | Q3-2021 | 1 | -10 | 700 | N | Y |
P003 | Q4-2021 | 2 | 100 | -800 | Y | N |
P003 | Q2-2022 | 3 | -90 | 100 | Y | Y |
P003 | Q1-2022 | 3 | -100 | -900 | Y | Y |
select P1.projectID, P1.quarterYear, P1.Rank, P1.planned_Delta, P1.actual_Delta,
case when Rank = X1.RankMin then 'N' ELSE 'Y' END plannedFlag ,
case when Rank = X2.RankMin then 'N' ELSE 'Y' END actualFlag
from payBackTable P1
left join (
select projectID, min(Rank) RankMin
from payBackTable P2
where Planned_Delta < 0
group by projectID
) X1 on P1.projectID = X1.projectID
left join (
select projectID, min(Rank) RankMin
from payBackTable P2
where Actual_Delta < 0
group by projectID
) X2 on P1.projectID = X2.projectID