AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Komplizierte SQL-Abfrage

Ein Thema von EmWieMichael · begonnen am 10. Jul 2020 · letzter Beitrag vom 13. Jul 2020
Antwort Antwort
Seite 1 von 2  1 2      
EmWieMichael

Registriert seit: 28. Mär 2012
103 Beiträge
 
#1

Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 08:36
Datenbank: SQL-Server • Version: alle • Zugriff über: Devart
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.

Geändert von EmWieMichael (10. Jul 2020 um 09:06 Uhr) Grund: Beispieldaten angefügt
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.354 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 09:13
Da du dich mit SQL auskennst, wie du schreibst, werfe ich hier mal nur "exists" in den Raum
Peter
  Mit Zitat antworten Zitat
Benutzerbild von KodeZwerg
KodeZwerg

Registriert seit: 1. Feb 2018
3.691 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 09:40
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...
Gruß vom KodeZwerg

Geändert von KodeZwerg (10. Jul 2020 um 09:45 Uhr)
  Mit Zitat antworten Zitat
Jumpy

Registriert seit: 9. Dez 2010
Ort: Mönchengladbach
1.736 Beiträge
 
Delphi 6 Enterprise
 
#4

AW: Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 09:56
Diese Bedingung:

Zitat:
eine beliebige Anzahl Auftragssätze besitzen, davon aber mindestens ein Satz, nicht vom Typ n ist.
würde ich umformulieren in:

Zitat:
die mindestens einen Auftragssatz besitzen, der nicht Typ n ist.
Dann sieht man die Lösung leichter: Einfach beide Tabellen per Left Join zur Personen-Tabelle joinen, mit entsprechenden Where-Bedingungen.
Ralph
  Mit Zitat antworten Zitat
Benutzerbild von dataspider
dataspider

Registriert seit: 9. Nov 2003
Ort: 04539 Groitzsch
1.351 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 10:02
So als Prinzip:

SQL-Code:

select * 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)
        )
    )
Frank
Frank Reim
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.205 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 10:06
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.
  Mit Zitat antworten Zitat
Benutzerbild von Jasocul
Jasocul

Registriert seit: 22. Sep 2004
Ort: Delmenhorst
1.354 Beiträge
 
Delphi 11 Alexandria
 
#7

AW: Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 10:47
@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.
Peter
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.205 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 10:54
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.
  Mit Zitat antworten Zitat
EmWieMichael

Registriert seit: 28. Mär 2012
103 Beiträge
 
#9

AW: Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 11:11
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!
  Mit Zitat antworten Zitat
Rainbow6

Registriert seit: 21. Mai 2019
20 Beiträge
 
#10

AW: Komplizierte SQL-Abfrage

  Alt 10. Jul 2020, 21:10
Es empfiehlt sich immer so eine Abfrage mit WITH aufzubauen - also z.B.:

Code:
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)
...
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.

Grüße
Daniel
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 17:47 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz