![]() |
Datenbank: SQL-Server • Version: alle • Zugriff über: Devart
Komplizierte SQL-Abfrage
Hallo SQL-Spezis!
Obwohl ich bereits seit einiger Zeit mit SQL arbeite, weiß ich für das nachfolgend beschriebene Problem nichteinmal ansatzweise eine Lösung. Gegeben sind folgende Tabellen: - PERSON - EIGENSCHAFT - AUFTRAG Die Tabellen EIGENSCHAFT und AUFTRAG enthalten zu jedem Personensatz 0..n Sätze. Die logische Verbindung wird über Nummernfelder realisiert: PERSON.NUM enthält einen einmaligen Integerwert, EIGENSCHAFT.PNUM und AUFTRAG.PNUM erhalten PERSON.NUM und "zeigen" so auf den entsprechenden Personensatz. Die Auftragstabelle enthält u. a. das Feld AUFTRAG.TYP (Integer) mit Werten zwischen 1 und 20. So, nun zu meinem Problem: Ich möchte sämtliche Personen selektieren, die a) über mindestens eine Eigenschaft verfügen, und (!) b) entweder keine Auftragssätze besitzen, oder (!) eine beliebige Anzahl Auftragssätze besitzen, davon aber mindestens ein Satz, nicht vom Typ n ist. Selbstredend ist es der b)-Teil der Abfrage, der meine Stirn in Falten legt. Lässt sich die Abfrage überhaupt mit SQL realisieren? Ich bin für jeden Tipp dankbar! Michael EDIT Ein Beispiel: PERSON NUM NAME 10 Müller 11 Meyer 12 Schmidt 13 Schulze EIGENSCHAFT PNUM WERT 10 Musiker 10 Handballer 11 Tänzer 12 Angler 12 Segler AUFTRAG PNUM TYP 10 5 10 8 11 5 13 8 13 9 Setze ich z. B. als Ausschlusskriterium AUFTRAG.TYP = 5 (b-Teil der Abfrage) ein, muss die Abfrage zu folgendem Ergebnis führen: 10 Müller (er hat mindestens eine Eigenschaft, und einen Auftragssatz <> Typ 5) 12 Schmidt (er hat mindestens eine Eigenschaft, und keinen Auftragssatz) Nicht im Seklektionsergebnis: Meyer hat zwar eine Eigenschaft, aber nur Aufrtagssatz vom Typ 5. Schulze hat zwar einen Auftragssatz <> Typ 5, aber keine Eigenschaft. |
AW: Komplizierte SQL-Abfrage
Da du dich mit SQL auskennst, wie du schreibst, werfe ich hier mal nur "exists" in den Raum
|
AW: Komplizierte SQL-Abfrage
Ich bin echt kein DB Mensch, lasse mir da lieber von "Fertigprodukten" helfen, aber kommt man da nicht besser mit einer "IFNULL()" abfrage voran?
//edit ich vermute das ich eher "WHERE spalteXYZ IS NOT NULL" meinte... |
AW: Komplizierte SQL-Abfrage
Diese Bedingung:
Zitat:
Zitat:
|
AW: Komplizierte SQL-Abfrage
So als Prinzip:
SQL-Code:
Frankselect * from person p where exists(select * from eigenschaft e where e.pnum = p.enum) and ( not exists(select * from auftrag a where a.pnum = p.enum) or ( exists(select * from auftrag a1 where a1.pnum = p.enum) and exists(select * from auftrag a2 where a2.pnum = p.enum and a2.typ <> 5) ) ) |
AW: Komplizierte SQL-Abfrage
Ich möchte sämtliche Personen selektieren, die
select * from Person p where ( a) über mindestens eine Eigenschaft verfügen, 1<=(select Count(*) from eigenschaft e where e.pid=p.id) und (!) and ( b) entweder keine Auftragssätze besitzen, 0=(select Count(*) from auftrag a where a.pid=p.id) oder (!) or eine beliebige Anzahl Auftragssätze besitzen, davon aber mindestens ein Satz, nicht vom Typ n ist. 1<=(select Count(*) from auftrag a where a.pid=p.id and typ <> n) )) Wobei hier "beliebige Anzahl" als "mind.1" verstanden wird. |
AW: Komplizierte SQL-Abfrage
@TigerLilly:
Deine Variante dürfte auch funktionieren, ist aber deutlich langsamer als eine Lösung mit exists. Exists hört auf zu arbeiten, sobald ein Datensatz getroffen wurde. Ein Count muss ja trotzdem ermitteln, wie viele Treffer es gibt. |
AW: Komplizierte SQL-Abfrage
Ja, das ist grundsätzlich richtig. Ich wollte nur eine pädagogische Lösung nahe an der Fragestellung, von der aus man weiter optimieren kann.
|
AW: Komplizierte SQL-Abfrage
Hui, seid Ihr flott :).
Das Exists-Statement scheint ja der richtige Ansatz zu sein. Leider schaffe ich es heute nicht mehr, die gezeigten Varianten zu testen. Montag geht es weiter... Herzlichen Dank für Eure Hilfe! :thumb: |
AW: Komplizierte SQL-Abfrage
Es empfiehlt sich immer so eine Abfrage mit WITH aufzubauen - also z.B.:
Code:
Durch das WITH hast du die Möglichkeit, deine Abfragen Stück für Stück zu testen und zu strukturieren - und die meisten Query Optimizer haben es damit auch leichter - zumindest ist das bei DB2 so.
WITH
PersonenOhneAuftrag AS ( SELECT pnum FROM Auftrag GROUP BY pnum HAVING COUNT(*) = 0 ), PersonenOhneNAuftrag AS ( SELECT pnum FROM Auftrag WHERE Typ <> N GROUP BY pnum ), ... SELECT * FROM Person WHERE num NOT IN (SELECT pnum FROM PersonenOhneAuftrag) OR num IN (SELECT pnum FROM PersonenOhneNAuftrag) ... Grüße Daniel |
Alle Zeitangaben in WEZ +1. Es ist jetzt 04:05 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz