SQL Abfrage Problem

Hallo !

ich krieg eine SQL Abfrage irgendwie nicht hin…
Ich habe die Tabellen “Person”, “Reiter”, “Reitlehrer”, “Azubi”.
“Reiter”, “Reitlehrer”, “Azubi” sind alles Personen, haben also jeweils eine verbindung zu einem “Person” Datensatz. Nun gibt es aber auch neutrale Personen, die nicht Reiter, Reitlehrer bzw. Azubis sind.

Ich möchte nun gerne aus der Tabelle “Person” nur alle neutralen Personen haben… wie geht das ?

Danke schonmal im voraus,
Nadine

Hier nochmal die Tabellen (mit nur paar bzw. relevanten Spalten):

Person

per_id int8
per_name text
per_vorname text


Reiter

rei_id int8
rei_perid int8 – Verbindung zum Person Datensatz
rei_art

Azubi

azp_id int8
azp_perid int8 – Verbindung zum Person Datensatz
azp_berufsbezeichnung text

Reitlehrer

rtl_id int8
rtl_perid int8 – Verbindung zum Person Datensatz
rtl_eignunglonge int4

Hmm, dafür ist dein Datenmodell nicht wirklich gut geeignet. Du solltest am besten in der Personentabelle vermerken, welche Person was ist …

Ansonsten ein Beispiel, wie du (aber sicherlich ziemlich langsam) die gewünschten Daten finden kannst:

SELECT * FROM person WHERE per_id NOT IN (SELECT azp_id from azubi) AND per_id NOT IN (SELECT rei_id FROM reiter) AND per_id NOT IN (SELECT rtl_id FROM reitlehrer)
[/quote]

Ev. lässt sich mit einem LEFT/RIGHT Join und einer Abfrage der Spalten mit NULL das gleiche Ergebnis erzielen.

Bleibt zu sagen: du musst in jedem Fall die komplette Tabelle Azubi, Reiter und Reitlehrer durchsuchen, um deine Frage zu beantworten: aus Datenbanksicht ist das sehr teuer.

Falls das geht. Hier scheint es zu gehen, es sei denn, ein Azubi kann auch Reiter sein.

Ansonsten ein Beispiel, wie du (aber sicherlich ziemlich langsam) die gewünschten Daten finden kannst:

SELECT * FROM person WHERE per_id NOT IN (SELECT azp_id from azubi) AND per_id NOT IN (SELECT rei_id FROM reiter) AND per_id NOT IN (SELECT rtl_id FROM reitlehrer)
[/quote]

Vielleicht auch

[code]
… where per_id not in (select rei_perid from reiter union select azp_perid from azubi union select rtl_perid from reitlehrer).

>
> Das wäre u.U. einfacher, weil nur ein Vergleich via NOT IN (...)
>
> > Bleibt zu sagen: du musst in jedem Fall die komplette Tabelle Azubi, Reiter und Reitlehrer durchsuchen, um deine Frage zu beantworten: aus Datenbanksicht ist das sehr teuer.
>

Allerdings.
\
\
Andreas



Person
-----------------------
  per_id int8
  per_name text 
  per_vorname text
ist_azubi boolean
ist_reiter boolean
ist_reitlehrer boolean



SELECT * FROM personen WHERE ist_azubi=false AND ist_reiter=false AND ist_reitlehrer=false

Problem erledigt.

Nicht wirklich. Vielleicht willst Du eines Tages noch die Merkmale ‘schon_mal_gefallen’, ‘hat_geschwister’ und ‘ist_zu_pferden_nett’ speichern. Dann baust Du die Tabelle um.

Andreas

Gut, dann lagerst du diese Werte alle in eine einzelne 1:n Tabelle aus, dann ist der Abfrageaufwand auch auf eine lineare Abfrage reduziert.

Du könntest auch z.B. mit Vererbung arbeiten, also z.B. eine Tabelle Person anlegen, die ihre Attribute an Tabellen Reitlehrer, Azubi und Reiter vererbt. Du könntest das in den Child-Tabellen jeweils spezifische Attribute anlegen.
Allerdings kann das Probleme mit Foreign-Keys erzeugen und ich weiß auch nicht, ob das der Rat der grösseren Experten hier wäre. Aber eine Möglichkeit wäre es.

Gruß Uwe

Die Vererbung macht IMHO mehr Probleme als sie löst… aber manche verwenden das wohl dennoch gerne. Für solche Dinge wie oben prinzipiell keine schlechte Idee.

Andreas

Bleibt für Nadine01 zusammenzufassen: Du solltest dein Datenmodell noch mal überarbeiten, falls das möglich ist.

Auf verschiedenen anderen Wegen kommst du schneller und eleganter zu deinem Ergebnis.

Na jungs, macht ihr schon wieder Hausaufgaben? :slight_smile:

Ich würde ein vollständiges Rollenmodell vorschlagen

table role

pk
rolename (reiter, azubi, trainer, fußpfleger, was auch immer)

table personen

personendaten

table person2role

personpk
rolepk





Erfolgreiches neues Jahr


Jochen

Was macht der Azubi, der Fußpfleger lernt, und in der Freizeit reitet?

Andreas

hmm, role attributes?

table role_attributes

pkey
person2rolepk
lernt_beruf varchar (255),
longiert_nur varchar(10),
schläft_mit INT8[], (oder ne weitere n:m)

oder du packst die daten in person …

@nachtrag
jede person kann jede rolle haben

Jetzt setzt du akretschmer und meinen Vorschlag um … nur komplizierter.

stimmt gewissermaßen

Hi !

vielen vielen Dank für die Hilfe und die zahlreichen Antworten - da hab ich ja eine richtige diskussion entfacht :wink:

Die Querys, die ihr gepostet hattet haben irgendwie nicht ganz funktioniert gehabt, da hab ich immer ein leeres Ergebnis zurückbekommen, obwohl eigentlich 3 Datensätze rauskommen müssten. Ein bisschen umgewandelt geht es dann aber:

SELECT * FROM person where
per_id not in
(select per_id from person, reiter where rei_perid = per_id union
select per_id from person, reitlehrer where rtl_perid = per_id union
select per_id from person, azubi where azp_perid = per_id)

Warum auch immer das aber ohne die Verknüpfung in den einzelnen selects nicht ging…kein Plan…?! :confused:


Schlussendlich hab ich dann aber doch die Felder isReiter, isReitlehrer, isAzubi in meine Person Tabelle miteingefügt.
Da hat ich zu beginn der tabellenentwicklung schon mit geliebäugelt, das aber aus irgendeinem Grund nich gemacht. Da ich nicht mehr weiss warum - isses nu drin… :slight_smile:

Danke nochmal,
Nadine