Oracle CONNECT BY Anzeige der maximalen Verkettung
Von Tobias Arnhold →
12.26.2014
Der Umgang mit CONNECT BY ist für mich immer wieder ein Highlight. Ob Positiv oder Negativ lasse ich mal außen vor. :)
Unbeachtet meiner Meinung ist es die sinnvollste Lösung um Baum-Verkettungen zu generieren.
Eine Anforderung die ich zuletzt gleich zweimal lösen musste war die Darstellung der finalen Ketten.
Beispiel Quell-Daten:
1:
1:2
1:2:3
1:2:4
1:6
1:6:1
Beispiel Ziel-Daten:
1:2:3
1:2:4
1:6:1
Das Ganze war recht einfach mit Hilfe einer analytischen Funktion zu lösen:
Unbeachtet meiner Meinung ist es die sinnvollste Lösung um Baum-Verkettungen zu generieren.
Eine Anforderung die ich zuletzt gleich zweimal lösen musste war die Darstellung der finalen Ketten.
Beispiel Quell-Daten:
1:
1:2
1:2:3
1:2:4
1:6
1:6:1
Beispiel Ziel-Daten:
1:2:3
1:2:4
1:6:1
Das Ganze war recht einfach mit Hilfe einer analytischen Funktion zu lösen:
-- Tabele Definition CREATE TABLE "T_ROUTE_EXAMPLE" ( "ID" NUMBER, "P_ID" NUMBER, "NAME" VARCHAR2(50), "TYPE" VARCHAR2(20), PRIMARY KEY ("ID") ) ; -- Data REM INSERTING into T_ROUTE_EXAMPLE SET DEFINE OFF; Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('1',null,'Haus S','BUILDING'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('3','1','Switch_S_1','SWITCH'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('4','3','1/3','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('5','3','2/3','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('6','3','3/3','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('7','1','Switch_S_2','SWITCH'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('8','7','1/2','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('9','7','2/2','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('10','4','DHCP Server','SERVER'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('11','5','orclapex DB Server','SERVER'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('12','6','ORDS Server','SERVER'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('13','8','WEB Server','SERVER'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('14','9','AD Server','SERVER'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('15',null,'Haus G','BUILDING'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('16','15','Switch_G_1','SWITCH'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('17','16','1/3','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('18','16','2/3','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('19','16','3/3','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('20','17','Win Client 1','CLIENT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('21','18','Win Client 2','CLIENT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('22','19','Mac Client 1','CLIENT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('23',null,'Haus D','BUILDING'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('24','23','Switch_D_1','SWITCH'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('25','24','1/2','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('26','24','2/2','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('27','23','Switch_D_2','SWITCH'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('28','27','1/2','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('29','27','2/2','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('30','23','Switch_D_3','SWITCH'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('31','30','1/2','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('32','30','2/2','PORT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('33','28','Mac Client 2','CLIENT'); Insert into T_ROUTE_EXAMPLE (ID,P_ID,NAME,TYPE) values ('34','29','Mac Client 3','CLIENT');Hier das Select um das entsprechende Ergebnis zu generieren:
SELECT PATH_LENGTH, ID, P_ID, NAME, TYPE, ID_LIST, NAME_LIST, TYPE_LIST FROM ( SELECT case when instr(':'||LEAD(ID_LIST) OVER (ORDER BY ID_LIST)||':',':'||ID_LIST||':') > 0 then null else 'OK' end as FINAL_PATH, PATH_LENGTH, ID, P_ID, NAME, TYPE, ID_LIST, NAME_LIST, TYPE_LIST FROM ( SELECT LEVEL as PATH_LENGTH, ID, P_ID, NAME, TYPE, SUBSTR(SYS_CONNECT_BY_PATH(ID, ':'),2) as ID_LIST, SUBSTR(SYS_CONNECT_BY_PATH(NAME, ':'),2) as NAME_LIST, SUBSTR(SYS_CONNECT_BY_PATH(TYPE, ':'),2) as TYPE_LIST FROM T_ROUTE_EXAMPLE M1 start with M1.P_ID is null CONNECT BY prior M1.ID = M1.P_ID ) ) WHERE FINAL_PATH = 'OK'