Как написать вовлеченный рекурсивный подзапрос в sqlplus с несколькими таблицами для отслеживания узлов? - PullRequest
0 голосов
/ 17 апреля 2019

Я пытаюсь создать отчет, который сопоставляет нагрузки в цепи с соответствующим источником питания (трансформатором).

Все устройства находятся в отдельных таблицах и взаимосвязаны в базе данных: нагрузки, коммутаторы, линии, Провода, Трансформаторы.

Для простоты я покажу пример, где нагрузка подключается к трансформатору напрямую только через переключатели:

Таблица нагрузки:

LoadNumber, SectionNumber, BusNumber
100         54             3000

Таблица переключателей:

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

Таблица трансформаторов:

TransformerNumber, FromSectionNumber, ToSectionNumber, FromBus, ToBus
5000               800                700              2000     3000
5001               801                701              2000     3000

В приведенном выше примере трансформатор # 5000 подключен к нагрузке # 100 через подключение через переключатели в таблице и под напряжениемпотому что есть замкнутая цепь (замкнутые переключатели, связывающие трансформатор и нагрузку вместе).

Я пытаюсь написать запрос, который может генерировать вывод, похожий на что-то вроде этого:

LoadNumber, TransformerNumber
100         5000

Это означает, что нагрузка № 100 питается от трансформатора # 5000

. Мне удалось успешно получить запрос, используя 1 таблицу (переключатели), чтобы найтиС трансформатором они связаны, но я немного растерялся из-за того, как задействовать все таблицы, чтобы получить полное представление о сети.

До сих пор я получил:

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

Я уже давно с этим играюсь и не уверен, какая часть этого запроса испорчена.

Редактировать:

Если бы я хотел написать запрос для получения желаемого результата, используя примерный набор данных, как бы это было достигнуто?

Что-то с логикой: выбрать номер нагрузки, номер трансформатора, где нагрузка подключена к трансформатору под напряжением через замкнутые устройства переключения?

1 Ответ

1 голос
/ 17 апреля 2019

В вашем упрощенном примере (вроде, я начал использовать ваши настоящие имена таблиц, но это исходные данные) вы можете получить все маршруты через несколько коммутаторов с помощью:

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

дб <> скрипка

Добавление в другие таблицы, очевидно, немного усложнит ситуацию, но не совсем понятно, как они все связаны.

...