Abfrage über Tabellen deren Name in einer Tabelle stehen

enseth439

Aktiver Benutzer
Beiträge
25
Hallo, meine SQL Kenntnisse reichen leider nicht aus das gesuchte in einer einzelnen Abfrage zu erledigen. Problem ist hier, dass die Tabellennamen in einer Tabelle stehen.

Die Tabellen sehen in etwa so aus:
Code:
main: id, tabelle-x, id-x, plz, geloescht
x1: id, endedatum, geloescht
x2: id, endedatum, geloescht

Gesucht sind jetzt jeweils alle Postleitzahlen sortiert nach nicht gelöscht und deren Endedatum, ohne doppelte PLZ. Endedatum kann auch mal leer sein, dann ist geloescht = 0 sonst -1. Die id-x ist nicht eindeutig, also jede Tabelle-x kann z.B. die ID 120 haben.

Ist das überhaupt möglich in einer Abfrage?
 
Zuletzt bearbeitet:
Werbung:

akretschmer

Datenbank-Guru
Beiträge
9.846
Hallo, meine SQL Kenntnisse reichen leider nicht aus das gesuchte in einer einzelnen Abfrage zu erledigen.
Problem ist hier, dass die Tabellennamen in einer Tabelle stehen (deren Name stimmt noch nicht mal mit den wirklichen Tabellennamen überein).

Die Tabellen sehen in etwa so aus:

main: id, tabelle-x, id-x, plz, geloescht
x1: id, endedatum, geloescht
x2: id, endedatum, geloescht

Gesucht sind jetzt jeweils alle Postleitzahlen sortiert nach nicht gelöscht und deren Endedatum ohne doppelte PLZ. Endedatum kann auch mal leer sein, dann ist geloescht = 0 sonst -1. Die id-x ist nicht eindeutig, also jede Tabelle-x kann z.B. die ID 120 haben.

Ist das überhaupt möglich in einer Abfrage?

Das klingt etwas wirr. Kannst Du das mal an einem Beispiel zeigen?

Wenn der Tabellennamen in einer Spalte steht wird es darauf hinauslaufen, dynamisches SQL zu generieren und dieses via EXECUTE auszuführen. Für PG ist das kein Ding (für mich), mit M$SQL kenn ich mich nicht aus, aber der @ukulele kommt bestimmt auch gleich ;-)
 

enseth439

Aktiver Benutzer
Beiträge
25
Hier ein Beispiel
Code:
main:
id, tabelle-x, id-x, plz, geloescht
100, x1, 150, 21029, -1
101, x2, 200, 21029, 0
...

x1:
id, endedatum, geloescht
150, 01.10.2013, -1
...

x2:
id, endedatum, geloescht
200, <null>, 0
...

Soll liefern:
id, tabelle-x, id-x, plz, geloescht,endedatum
101, x2, 200, 21029, 0, <null>
...

Danke fürs draufschauen...
 
Zuletzt bearbeitet:

ukulele

Datenbank-Guru
Beiträge
4.702
Also EXECUTE ist kein Ding sollte sich nicht von PG unterscheiden und das ist hier auch notwendig, da stimme ich zu.
 

ukulele

Datenbank-Guru
Beiträge
4.702
Ok wenn ich das Problem mal genauer betrachte (sry hatte neulich nicht die Ruhe) dann ist dynamisches SQL sehr mühselig, man müsste schon mit einer Schleife einen Select zusammen kleistern. Sind es wirklich viele Tabellen oder hält sich die Anzahl in Grenzen? Ansonsten könnte man auch mit einer CASE Schleife und Subselects oder UNION arbeiten.
 

ukulele

Datenbank-Guru
Beiträge
4.702
Code:
SELECT    m.id,
        m.tabelle-x,
        m.id-x,
        m.plz,
        m.geloescht,
        x1.enddatum AS enddatum
FROM    main m
LEFT JOIN x1 ON m.id-x = x1.id
WHERE    m.tabelle-x = 'x1'
UNION ALL
SELECT    m.id,
        m.tabelle-x,
        m.id-x,
        m.plz,
        m.geloescht,
        x2.enddatum AS enddatum
FROM    main m
LEFT JOIN x2 ON m.id-x = x2.id
WHERE    m.tabelle-x = 'x2'
 

enseth439

Aktiver Benutzer
Beiträge
25
Grob sind das 10 Tabellen. Alle paar Jahre kommt mal eine dazu. Dann heißt es wohl die Abfrage anpassen. Mit UNION sieht das sehr übersichtlich aus, würde sich dann aber ganz schön oft wiederholen :). Geht das mit CASE vielleicht kompakter? Brauche ich dann ein CASE im JOIN und im WHERE Statement?

Ein Problem ist noch die Sortierung. Wenn es einen aktiven Eintrag gibt, sollen weitere gelöschte nicht als Ergebnis ausgegeben werden, ansonsten nur der zuletzt gelöschte. Mit FIRST und GROUP BY sollte das gehen.
Code:
SELECT mit FIRST(...) außer PLZ
...
LEFT JOIN ON
    m.tabelle-x = CASE....
WHERE ...
    m.tabelle-x = CASE....
GROUP BY
  (m.plz)
ORDER BY
  First(m.plz),
  First(m.geloescht) DESC

Ja, enddatum fehlt noch. Das kommt bestimmt aus der Schleife mit dem Subselect.
Wie jetzt nochmal Schleife und Subselect?
:( Öh, schönes Ding.
 
Zuletzt bearbeitet:

ukulele

Datenbank-Guru
Beiträge
4.702
Man kann alles dynamisch zusammen kleistern aber ich denke UNION ist schlichter und wenn man alle mit UNION verkettete Selects noch als Subselect nimmt kann man auch sortieren.
Code:
SELECT    asdf
FROM (
SELECT    asdf
FROM    qwert1
UNION ALL
SELECT    asdf
FROM    qwert2
) tabelle
ORDER BY asdf
Ich frage mich aber auch warum die Daten erst in verschiedene Tabellen zerlegt werden um dann wieder zusammengeklebt zu werden :)
 

enseth439

Aktiver Benutzer
Beiträge
25
Das Datenbankkonzept ist fragwürdig. Gedacht ist es wohl so, dass man abfragt in welcher Tabelle man schauen soll und dann dort noch mal eine Abfrage nach dem Ergebnis stellt. Es wird dann immer nur eine weitere Tabelle benötigt. Ich bin jetzt der Held, der die Tabellen ausnahmsweise zusammenkleben will, um die letzt gültigen Einträge über alle Tabellen zu finden. :eek:

Partitionierung: Das ist sicher eine tolle Sache, aber da die Datefunktion hinzukriegen ist über meinem Können.

Ich kriege das nicht mal mit CASE hin und werde das jetzt mal mit UNION auf zwei Tabellen probieren. So wie ukulele das vorgeschlagen hat. Wenn das geht, dann kommen die anderen noch hinzu bzw. lasse ich den SQL String mittels einer Programmschleife zusammensetzen. Dann wäre ich schon glücklich.
 
Zuletzt bearbeitet:

enseth439

Aktiver Benutzer
Beiträge
25
Das sah eigentlich ganz gut aus, aber FIRST und LAST gibt es nicht in MSSQL als Aggregatfunktion (das hatte in ACCESS zusammengebaut). MIN und MAX sind kein Ersatz und verhalten sich anders. Also muss die Sortierung noch mal angepasst werden...
 
Zuletzt bearbeitet:

ukulele

Datenbank-Guru
Beiträge
4.702
Ich kenne jetzt FIRST und LAST nicht aber hört sich an wie
Code:
SELECT TOP 1 spalte FROM tabelle ORDER BY spalte
und
SELECT TOP 1 spalte FROM tabelle ORDER BY spalte DESC
Zugegeben TOP ist sehr gewöhnungsbedürftig. Manchmal wünsche ich mir auch LIMIT in MSSQL.
 

enseth439

Aktiver Benutzer
Beiträge
25
TOP1 liefert den ersten Datensatz. In UNION dann jeweils einen je Tabelle. Dann könnte man zwar gruppieren, das würde aber nicht einen Datensatz je Gruppe liefern sondern je Tabelle.

"Top 1 row of each group" heißt das Problem. Die Lösungen lauten z.B. so:

ROW_NUMBER() OVER (PARTITION BY DocumentID ORDER BY DateCreated DESC) AS rn
WHERE rn =1

PARTITION BY, wenn das akretschmer mit Partitionierung gemeint hat, ziehe ich meinen Hut :D.

Es gibt auch noch weitere Möglichkeiten über JOIN. Naja, das probiere ich gerade aus. Es ist aber nicht so einfach für mich.
 
Werbung:
Oben