Komplexer Subselect

Lionheart

Benutzer
Beiträge
6
Hallo Miteinander


Ich habe hier eine Knacknuss mit der ich einfach nicht weiter komme, ich hoffe jemand kann mir weiter helfen:


Ich habe folgende Tabellen: Leitungen,Pfade,Kabel,Pfadkabel


Ich möchte alle Leitungen selektieren die jeweils einen Pfad (und ergo die dazugehörigen Kabel) benutzen der länger als 1300m ist. Mit meiner Selektion kriege ich leider auch diejenigen Leitungen die sich auf einem kürzeren Pfad befinden der eines oder mehrere Kabel des längeren Pfades benutzt. Ich will aber nur diejenigen Leitungen die sich GENAU auf diesem einen Pfad befinden der länger als 1300m ist, also nur die Leitungen die alle Kabel des gewünschten Pfades (<1300m) benutzen und KEINES mehr oder weniger.


Man müsste also ausdrücken können:

Selektiere alle Leitungen bei denen es kein Kabel im Pfad gibt das nicht in der Leitung vorhanden ist.



select distinct Leitung.id,Pfad.realdistanz,Pfad.id
from leitungen,pfade,kabel, pfadkabel
where pfad.realdistanz>1300
and pfad.id=Pfadkabel.Pfad_id
and Pfadkabel.kabel_id=kabel.id
and kabel.id=leitung.kbl_id;




Weil das (zumindest für mich) doch schon ganz komplex tönt, habe ich das beilegend noch etwas illustriert:


Ich hoffe ihr versteht meinen Ansatz und danke Euch ganz herzlich für Eure wertvolle Hilfe.


Grüsse Lionheart
 

Anhänge

  • LTG_KBL.jpg
    LTG_KBL.jpg
    34,3 KB · Aufrufe: 5
Werbung:
1. benutze bitte saubere JOIN-Anweisungen und trenne damit auch JOIN und WHERE - Condition
2. zeige mitte die Definition der Tabellen und einige Demo-Datensätze, am besten gleich als CREATE TABLE und INSERT - Statements.
 
Hallo

Tut mir leid, das ist mein erster Eintrag - anbei die gewünschten Informationen:

select distinct Leitung.id,Pfad.realdistanz,Pfad.id
from
leitungen,pfade,kabel, pfadkabel
where
pfad.realdistanz>1300
and pfad.id=Pfadkabel.Pfad_id
and Pfadkabel.kabel_id=kabel.id
and kabel.id=leitung.kbl_id;

Die Tabellen sehen in etwa so aus:

Leitungen Pfade
----------------
id kbl.id
1 11
2 12
3 13
 
Sorry...nochmals...Beitrag ging zu früh weg und ich konnte ihn anschliessend nicht mehr bearbeiten :oops::

Leitungen Pfade Kabel Pfadkabel
--------------------------------------------------------------------------------------------------------------------------------------
id | Kabel_id id | Distanz id Pfad_id | Kabel_id | Ref_nr (Lage im Kabel)
---------------------------------------------------------------------------------------------------------------------------------------
1 11 100 150.25 11 100 11 1
1 12 200 700.75 12 100 12 2
1 13 300 1350.00 13 300 11 1
2 11 300 12 2
2 12 300 13 3
3 11

Meinsch Wunsch wäre nun diejenigen Leitungen (Leitungen.id) mit dazugehörigen Pfad (Pfad.id) zu selektieren die jeweils aus Kabeln bestehen die exakt auf einen Pfad zutreffen der länger als 1300m ist. Dabei sollte im
obenstehenden Beispiel nur Leitungen.id=1 selektiert werden (obwohl die Kabel 11+12 jeweils in den Pfaden 100+300 vorkommen). Mit meinem statement kriege ich Leitungen.id=1,2,3 weil mind. 1 Kabel der Leitung in einem
Pfad ist der länger als 1300m ist.

Ich hoffe das Ganze ist so verständlich.

Gruss
 
Hat hier wirklich niemand eine Idee wie man das lösen könnte?

Offensichtlich. Dürfte schwer daran liegen, daß Dich wohl keiner versteht. Der Bitte, die Tabellenstruktur und Testdatensätze zu zeigen bist Du nicht nachgekommen. Dein Zahlenbrei mit 5 Kopfspalten und 8 Datenspalten hilft da auch nicht wirklich weiter.
 
Hallo akretschmer

Tut mir wirklich leid - ich habe es versucht aber scheinbar hat es mir hier die Formatierung zerrissen - ich starte einen neuen Versuch mit einem angehängten PDF File:

Vielen Dank für Deine Engelsgeduld :)

Gruss Lionheart
 

Anhänge

  • pfade.pdf
    194,8 KB · Aufrufe: 2
So, mit diesen Tabellen:

Code:
test=*# select * from pfadkabel ;
 pfad_id | kabel | ref_nr
---------+-------+--------
  100 |  11 |  1
  100 |  12 |  2
  300 |  11 |  1
  300 |  12 |  2
  300 |  13 |  3
(5 Zeilen)

test=*# select * from leitungen ;
 id | kabel_id
----+----------
  1 |  11
  1 |  12
  1 |  13
  2 |  11
  2 |  12
  3 |  11
(6 Zeilen)

test=*# select * from pfade ;
 id  | distanz
-----+---------
 100 |  150.25
 200 |  700.75
 300 |  1350
(3 Zeilen)

Wenn ich Dich richtig verstanden haben suchst Du nun:

Code:
test=*# select * from (select pfad_id, array_agg(kabel) as kabel from pfadkabel group by pfad_id) p left join (select id as leitungs_id, array_agg(kabel_id) as kabel from leitungen group by id) l on p.kabel=l.kabel left join pfade on p.pfad_id=pfade.id where pfade.distanz > 1300;
 pfad_id |  kabel  | leitungs_id |  kabel  | id  | distanz
---------+------------+-------------+------------+-----+---------
  300 | {11,12,13} |  1 | {11,12,13} | 300 |  1350
(1 Zeile)

Achtung: ich verwende kein MySQL, sondern PostgreSQL. Das wird sehr wahrscheinlich nicht 1:1 für Dich funktionieren.
 
Nachtrag:

die 2 Arrays, die als JOIN-Condition dienen, müssen nicht zwingend gleich sein, sie müssen aber beide dieselben Elemente enthalten, diese können aber in unterschiedlicher Reihenfolge vorkommen. Daher wäre es sicherer, dies so zu prüfen:

Code:
test=*# select * from (select pfad_id, array_agg(kabel) as kabel from pfadkabel group by pfad_id) p left join (select id as leitungs_id, array_agg(kabel_id) as kabel from leitungen group by id) l on (p.kabel @>l.kabel and p.kabel <@ l.kabel) left join pfade on p.pfad_id=pfade.id where pfade.distanz > 1300;
 pfad_id |  kabel  | leitungs_id |  kabel  | id  | distanz
---------+------------+-------------+------------+-----+---------
  300 | {11,12,13} |  1 | {11,12,13} | 300 |  1350
(1 Zeile)


@> und <@ prüfen, ob jeweils ein Array Bestandteil des anderen ist, also Contains. Wenn das ist beiden Richtungen TRUE ist dann ist unsere Condition erfüllt.

[code]
test=*# select array[1,2,3] @> array[2,3,1] and array[1,2,3] <@ array[2,3,1];
 ?column?
----------
 t
(1 Zeile)

während

Code:
test=*# select array[1,2,3] = array[2,3,1];
 ?column?
----------
 f
(1 Zeile)

Oder man sortiert die Arrays gleich:

Code:
test=*# select * from (select pfad_id, array_agg(kabel order by kabel) as kabel from pfadkabel group by pfad_id) p left join (select id as leitungs_id, array_agg(kabel_id order by kabel_id) as kabel from leitungen group by id) l on p.kabel=l.kabel left join pfade on p.pfad_id=pfade.id where pfade.distanz > 1300;
 pfad_id |  kabel  | leitungs_id |  kabel  | id  | distanz
---------+------------+-------------+------------+-----+---------
  300 | {11,12,13} |  1 | {11,12,13} | 300 |  1350
(1 Zeile)
 
Werbung:
Vielen herzlichen Dank! Ich habs zwar noch nicht wirklich begriffen und denke ich muss das ganze nach MYSQL übersetzen aber ich denke ich werde mich mal in diese Array Funktionen einlesen und kriege es damit sicher zu stande!

Einen schönen Abend wünsche ich Dir und vielen Dank für die Mühen die Du Dir gemacht hast, wirklich sehr nett!

Gruss Lionheart
 
Zurück
Oben