如何在带有多个表的sqlplus中编写涉及的递归子查询来跟踪节点?
How to write involved recursive subquery in sqlplus w/ multiple tables to trace nodes?
我正在尝试创建一个报告,将电路上的负载映射到它们各自的电源(变压器)。
所有设备都在单独的 table 中并在数据库中互连:负载、开关、线路、电线、变压器。
为了简单起见,我将展示一个负载仅通过开关直接连接到变压器的示例:
加载table:
LoadNumber, SectionNumber, BusNumber
100 54 3000
切换table:
SwitchNumber, FromSectionNumber, ToSectionNumber, State, BusNumber
1 54 105 Closed 3000
2 105 106 Closed 3000
3 106 500 Open 3000
4 105 999 Closed 3000
5 999 700 Closed 3000
变形金刚table:
TransformerNumber, FromSectionNumber, ToSectionNumber, FromBus, ToBus
5000 800 700 2000 3000
5001 801 701 2000 3000
在上面的示例中,变压器 #5000 通过 table 中的开关连接到负载 #100,并且因为存在闭合电路而通电(闭合开关将变压器和负载连接在一起) .
我正在尝试编写一个可以生成类似于以下内容的输出的查询:
LoadNumber, TransformerNumber
100 5000
这表示负载 #100 由变压器 #5000 供电
我能够使用 1 table(开关)成功获得查询以找到它们链接到的变压器,但我对如何涉及所有 tables 以获得网络的完整视图。
到目前为止我得到的是:
WITH T3 AS
(SELECT SWITCHNAME, SWITCHNUMBER, PSEUDOSWITCH, FROMSECTIONNUMBER, TOSECTIONNUMBER, NORMALSWITCHINGDEVICESTATE, BUSNUMBER
FROM SWITCHINGDEVICE
WHERE UPPER(NORMALSWITCHINGDEVICESTATE) = 'CLOSED'
AND BUSNUMBER = 3484),
T2 AS
(SELECT TRANSFORMERNUMBER, TRANSFORMERNAME, FROMSECTIONNUMBER, TOSECTIONNUMBER, FROMBUSNUMBER, TOBUSNUMBER
FROM TRANSFORMER
WHERE TOBUSNUMBER = 3484),
T4 AS
(SELECT DEVICENUMBER, DEVICENAME, FROMSECTIONNUMBER, TOSECTIONNUMBER, FROMBUSREF, TOBUSREF
FROM PSA_SERIESREACTIVEDEVICE
WHERE TOBUSREF = 3484),
T5 AS
(SELECT LINENUMBER, LINENAME, FROMSECTIONNUMBER, TOSECTIONNUMBER, FROMBUSNUMBER, TOBUSNUMBER
FROM LINE
WHERE TOBUSNUMBER = 3484 AND FROMBUSNUMBER = 3484),
T1 AS
(SELECT A.BUSNUMBER, A.LOADNUMBER, A.LOADNAME, B.TRANSFORMERNUMBER, B.TRANSFORMERNAME
FROM LOADDEFINITION A, TRANSFORMER B
WHERE A.LOADNUMBER = 5572
AND A.BUSNUMBER = B.TOBUSNUMBER
---TEST LOAD
UNION ALL
SELECT T1.BUSNUMBER, T1.LOADNUMBER, T1.LOADNAME, T2.TRANSFORMERNUMBER, T2.TRANSFORMERNAME
FROM LOADDEFINITION T1, TRANSFORMER T2, SWITCHINGDEVICE T3, PSA_SERIESREACTIVEDEVICE T4, LINE T5, SWITCHINGDEVICE T6
WHERE
T1.LOADNUMBER = 5572 AND T1.BUSNUMBER = 3484
AND T2.TOBUSNUMBER = T1.BUSNUMBER
AND T3.BUSNUMBER = T1.BUSNUMBER
AND T4.TOBUSREF = T1.BUSNUMBER
AND T5.TOBUSNUMBER = T1.BUSNUMBER
AND T5.FROMBUSNUMBER = T5.TOBUSNUMBER
AND T3.BUSNUMBER = T2.TOBUSNUMBER
AND T4.TOBUSREF = T2.TOBUSNUMBER
AND T5.TOBUSNUMBER = T2.TOBUSNUMBER
AND T3.BUSNUMBER = T4.TOBUSREF
AND T5.TOBUSNUMBER = T3.BUSNUMBER
AND T5.TOBUSNUMBER = T4.TOBUSREF
AND T6.BUSNUMBER = T1.BUSNUMBER
---take into consideration downstream loops
AND ((T1.SECTIONNUMBER = T3.TOSECTIONNUMBER AND T1.SECTIONNUMBER = T6.TOSECTIONNUMBER)
OR
(T1.SECTIONNUMBER = T3.FROMSECTIONNUMBER AND T1.SECTIONNUMBER = T6.FROMSECTIONNUMBER))
AND (T3.FROMSECTIONNUMBER = T2.TOSECTIONNUMBER)
AND (T3.FROMSECTIONNUMBER = T6.TOSECTIONNUMBER)
AND T6.NORMALSWITCHINGDEVICESTATE = T3.NORMALSWITCHINGDEVICESTATE
)
SELECT T1.BUSNUMBER, T1.LOADNUMBER, T1.LOADNAME, T2.TRANSFORMERNUMBER, T2.TRANSFORMERNAME FROM T1, T2
但我并没有像我期望的那样返回 1 个结果(因为我对单个负载进行了硬编码),而是返回了一个显示所有变压器的列表。
用示例数据表示,结果类似于:
LoadNumber, TransformerNumber
100 5000
100 5001
我已经研究这个问题一段时间了,不确定这个查询的哪一部分搞砸了。
编辑:
如果我想使用示例数据集编写查询以获得所需的结果,那将如何实现?
具有以下逻辑的东西:select loadnumber,transformernumber 其中负载通过闭合开关设备与变压器有带电连接?
在您的简化示例中(某种程度上,我开始使用您的真实 table 名称,但它是原始数据)您可以通过多个开关获取所有路由:
with rcte (rootsectionnumber, fromsectionnumber, tosectionnumber) as (
select fromsectionnumber, fromsectionnumber, tosectionnumber
from switchingdevice
where normalswitchingdevicestate = 'CLOSED'
union all
select r.rootsectionnumber, sd.fromsectionnumber, sd.tosectionnumber
from rcte r
join switchingdevice sd on sd.fromsectionnumber = r.tosectionnumber
)
select rootsectionnumber, tosectionnumber from rcte;
ROOTSECTIONNUMBER TOSECTIONNUMBER
----------------- ---------------
54 105
105 106
105 999
999 700
54 106
105 500
54 999
105 700
54 500
54 700
其中一个有一条从 54 路段到 700 路段的端到端路线;然后您可以将其加入负载定义:
with rcte (rootsectionnumber, fromsectionnumber, tosectionnumber) as (
select fromsectionnumber, fromsectionnumber, tosectionnumber
from switchingdevice
where normalswitchingdevicestate = 'CLOSED'
union all
select r.rootsectionnumber, sd.fromsectionnumber, sd.tosectionnumber
from rcte r
join switchingdevice sd on sd.fromsectionnumber = r.tosectionnumber
)
select ld.loadnumber, t.transformernumber
from loaddefinition ld
join rcte r on r.rootsectionnumber = ld.sectionnumber
join transformer t on t.tosectionnumber = r.tosectionnumber
where ld.loadnumber = 100;
LOADNUMBER TRANSFORMERNUMBER
---------- -----------------
100 5000
或者如果您需要在逻辑中包含 busnumber
(基于对较大查询的简要了解...):
with rcte (rootsectionnumber, busnumber, fromsectionnumber, tosectionnumber) as (
select fromsectionnumber, busnumber, fromsectionnumber, tosectionnumber
from switchingdevice
where normalswitchingdevicestate = 'CLOSED'
union all
select r.rootsectionnumber, r.busnumber, sd.fromsectionnumber, sd.tosectionnumber
from rcte r
join switchingdevice sd on sd.fromsectionnumber = r.tosectionnumber
and sd.busnumber = r.busnumber
)
select ld.loadnumber, t.transformernumber
from loaddefinition ld
join rcte r on r.rootsectionnumber = ld.sectionnumber
and r.busnumber = ld.busnumber
join transformer t on t.tosectionnumber = r.tosectionnumber
and t.tobusnumber = r.busnumber
where ld.loadnumber = 100;
LOADNUMBER TRANSFORMERNUMBER
---------- -----------------
100 5000
添加其他 table 显然会使事情复杂化一些,但尚不清楚它们之间的关系。
我正在尝试创建一个报告,将电路上的负载映射到它们各自的电源(变压器)。
所有设备都在单独的 table 中并在数据库中互连:负载、开关、线路、电线、变压器。
为了简单起见,我将展示一个负载仅通过开关直接连接到变压器的示例:
加载table:
LoadNumber, SectionNumber, BusNumber
100 54 3000
切换table:
SwitchNumber, FromSectionNumber, ToSectionNumber, State, BusNumber
1 54 105 Closed 3000
2 105 106 Closed 3000
3 106 500 Open 3000
4 105 999 Closed 3000
5 999 700 Closed 3000
变形金刚table:
TransformerNumber, FromSectionNumber, ToSectionNumber, FromBus, ToBus
5000 800 700 2000 3000
5001 801 701 2000 3000
在上面的示例中,变压器 #5000 通过 table 中的开关连接到负载 #100,并且因为存在闭合电路而通电(闭合开关将变压器和负载连接在一起) .
我正在尝试编写一个可以生成类似于以下内容的输出的查询:
LoadNumber, TransformerNumber
100 5000
这表示负载 #100 由变压器 #5000 供电
我能够使用 1 table(开关)成功获得查询以找到它们链接到的变压器,但我对如何涉及所有 tables 以获得网络的完整视图。
到目前为止我得到的是:
WITH T3 AS
(SELECT SWITCHNAME, SWITCHNUMBER, PSEUDOSWITCH, FROMSECTIONNUMBER, TOSECTIONNUMBER, NORMALSWITCHINGDEVICESTATE, BUSNUMBER
FROM SWITCHINGDEVICE
WHERE UPPER(NORMALSWITCHINGDEVICESTATE) = 'CLOSED'
AND BUSNUMBER = 3484),
T2 AS
(SELECT TRANSFORMERNUMBER, TRANSFORMERNAME, FROMSECTIONNUMBER, TOSECTIONNUMBER, FROMBUSNUMBER, TOBUSNUMBER
FROM TRANSFORMER
WHERE TOBUSNUMBER = 3484),
T4 AS
(SELECT DEVICENUMBER, DEVICENAME, FROMSECTIONNUMBER, TOSECTIONNUMBER, FROMBUSREF, TOBUSREF
FROM PSA_SERIESREACTIVEDEVICE
WHERE TOBUSREF = 3484),
T5 AS
(SELECT LINENUMBER, LINENAME, FROMSECTIONNUMBER, TOSECTIONNUMBER, FROMBUSNUMBER, TOBUSNUMBER
FROM LINE
WHERE TOBUSNUMBER = 3484 AND FROMBUSNUMBER = 3484),
T1 AS
(SELECT A.BUSNUMBER, A.LOADNUMBER, A.LOADNAME, B.TRANSFORMERNUMBER, B.TRANSFORMERNAME
FROM LOADDEFINITION A, TRANSFORMER B
WHERE A.LOADNUMBER = 5572
AND A.BUSNUMBER = B.TOBUSNUMBER
---TEST LOAD
UNION ALL
SELECT T1.BUSNUMBER, T1.LOADNUMBER, T1.LOADNAME, T2.TRANSFORMERNUMBER, T2.TRANSFORMERNAME
FROM LOADDEFINITION T1, TRANSFORMER T2, SWITCHINGDEVICE T3, PSA_SERIESREACTIVEDEVICE T4, LINE T5, SWITCHINGDEVICE T6
WHERE
T1.LOADNUMBER = 5572 AND T1.BUSNUMBER = 3484
AND T2.TOBUSNUMBER = T1.BUSNUMBER
AND T3.BUSNUMBER = T1.BUSNUMBER
AND T4.TOBUSREF = T1.BUSNUMBER
AND T5.TOBUSNUMBER = T1.BUSNUMBER
AND T5.FROMBUSNUMBER = T5.TOBUSNUMBER
AND T3.BUSNUMBER = T2.TOBUSNUMBER
AND T4.TOBUSREF = T2.TOBUSNUMBER
AND T5.TOBUSNUMBER = T2.TOBUSNUMBER
AND T3.BUSNUMBER = T4.TOBUSREF
AND T5.TOBUSNUMBER = T3.BUSNUMBER
AND T5.TOBUSNUMBER = T4.TOBUSREF
AND T6.BUSNUMBER = T1.BUSNUMBER
---take into consideration downstream loops
AND ((T1.SECTIONNUMBER = T3.TOSECTIONNUMBER AND T1.SECTIONNUMBER = T6.TOSECTIONNUMBER)
OR
(T1.SECTIONNUMBER = T3.FROMSECTIONNUMBER AND T1.SECTIONNUMBER = T6.FROMSECTIONNUMBER))
AND (T3.FROMSECTIONNUMBER = T2.TOSECTIONNUMBER)
AND (T3.FROMSECTIONNUMBER = T6.TOSECTIONNUMBER)
AND T6.NORMALSWITCHINGDEVICESTATE = T3.NORMALSWITCHINGDEVICESTATE
)
SELECT T1.BUSNUMBER, T1.LOADNUMBER, T1.LOADNAME, T2.TRANSFORMERNUMBER, T2.TRANSFORMERNAME FROM T1, T2
但我并没有像我期望的那样返回 1 个结果(因为我对单个负载进行了硬编码),而是返回了一个显示所有变压器的列表。
用示例数据表示,结果类似于:
LoadNumber, TransformerNumber
100 5000
100 5001
我已经研究这个问题一段时间了,不确定这个查询的哪一部分搞砸了。
编辑:
如果我想使用示例数据集编写查询以获得所需的结果,那将如何实现?
具有以下逻辑的东西:select loadnumber,transformernumber 其中负载通过闭合开关设备与变压器有带电连接?
在您的简化示例中(某种程度上,我开始使用您的真实 table 名称,但它是原始数据)您可以通过多个开关获取所有路由:
with rcte (rootsectionnumber, fromsectionnumber, tosectionnumber) as (
select fromsectionnumber, fromsectionnumber, tosectionnumber
from switchingdevice
where normalswitchingdevicestate = 'CLOSED'
union all
select r.rootsectionnumber, sd.fromsectionnumber, sd.tosectionnumber
from rcte r
join switchingdevice sd on sd.fromsectionnumber = r.tosectionnumber
)
select rootsectionnumber, tosectionnumber from rcte;
ROOTSECTIONNUMBER TOSECTIONNUMBER
----------------- ---------------
54 105
105 106
105 999
999 700
54 106
105 500
54 999
105 700
54 500
54 700
其中一个有一条从 54 路段到 700 路段的端到端路线;然后您可以将其加入负载定义:
with rcte (rootsectionnumber, fromsectionnumber, tosectionnumber) as (
select fromsectionnumber, fromsectionnumber, tosectionnumber
from switchingdevice
where normalswitchingdevicestate = 'CLOSED'
union all
select r.rootsectionnumber, sd.fromsectionnumber, sd.tosectionnumber
from rcte r
join switchingdevice sd on sd.fromsectionnumber = r.tosectionnumber
)
select ld.loadnumber, t.transformernumber
from loaddefinition ld
join rcte r on r.rootsectionnumber = ld.sectionnumber
join transformer t on t.tosectionnumber = r.tosectionnumber
where ld.loadnumber = 100;
LOADNUMBER TRANSFORMERNUMBER
---------- -----------------
100 5000
或者如果您需要在逻辑中包含 busnumber
(基于对较大查询的简要了解...):
with rcte (rootsectionnumber, busnumber, fromsectionnumber, tosectionnumber) as (
select fromsectionnumber, busnumber, fromsectionnumber, tosectionnumber
from switchingdevice
where normalswitchingdevicestate = 'CLOSED'
union all
select r.rootsectionnumber, r.busnumber, sd.fromsectionnumber, sd.tosectionnumber
from rcte r
join switchingdevice sd on sd.fromsectionnumber = r.tosectionnumber
and sd.busnumber = r.busnumber
)
select ld.loadnumber, t.transformernumber
from loaddefinition ld
join rcte r on r.rootsectionnumber = ld.sectionnumber
and r.busnumber = ld.busnumber
join transformer t on t.tosectionnumber = r.tosectionnumber
and t.tobusnumber = r.busnumber
where ld.loadnumber = 100;
LOADNUMBER TRANSFORMERNUMBER
---------- -----------------
100 5000
添加其他 table 显然会使事情复杂化一些,但尚不清楚它们之间的关系。