left join eingrenzen auf bestimmte Zeilen abhängig von Werten einer Spalte

abenteurer

Benutzer
Beiträge
5
Hallo,
ich habe folgendes Problem:

ich brauchen einen left join zwischen zwei Tabellen. Die beiden haben eine 1:n Beziehung. Nun will sowas wie eine "Prioritätenliste" für Tabelle 2 falls mehrere Einträge vorhanden sind.

Also etwa: Falls einer der Einträge in Tabelle 2 zu meiner ID in der Spalte A den Wert 1 hat, gib mir Werte aus dieser Zeile zurück. Gibt es keinen mit dem Wert 1 in Spalte A, aber einen mit dem Wert 3, dann die Einträge aus dieser Zeile, sonst nimm den mit 2. Wenn es alle drei nicht gibt, gib NULL zurück.

Hier stehe ich gerade völlig auf dem Schlauch & wäre für Hilfe dankbar. Hoffe, ich habe das Problem halbwegs verständlich beschrieben.

Datenbank ist SQL Server 2012
 
Werbung:

abenteurer

Benutzer
Beiträge
5
in Tabelle 1 habe ich Kunden:

ID | Name
---------------
1 | Name1
2 | Name2
3 | Name3
4 | Name4


in Tabelle 2 die dazugehörenden Adressen mit eine Adressart:

ID| Kunden_ID | Adressart | Strasse etc.
-----------------------------------------------
1 | 1 |4 |xxx
2 | 1 | 3 |yyy
3 | 2 |1 |zzz
4 | 2 |3 |aaa
5 | 3 |3 |bbb

Nun will ich immer nur eine Adresse in der Ausgabe haben und zwar wo vorhanden die mit der Adressart 4, falls es die zu einem Kunden nicht gibt, dann die mit der 1, sonst die 3. Wenn keine der drei vorhanden Null.

Gewünschtes Ergebnis:

Name1 xxx
Name2 zzz
Name3 bbb
Name4 NULL

Verständlicher?
 

ukulele

Datenbank-Guru
Beiträge
4.647
Code:
SELECT    *
FROM    kunden k
LEFT JOIN adressen a ON a.Kunden_ID = k.ID
WHERE    a.adressart = 4
OR        a.adressart = 1
AND NOT EXISTS    (    SELECT    1
                    FROM    adressen
                    WHERE    Kunden_ID = k.ID
                    AND        adressart = 4 )
OR        a.adressart = 3
AND NOT EXISTS    (    SELECT    1
                    FROM    adressen
                    WHERE    Kunden_ID = k.ID
                    AND    (    adressart = 4
                    OR        adressart = 1 ) )

Ich weiss nicht ob das von der Performance her problematisch ist aber das wäre ein Ansatz.
 

abenteurer

Benutzer
Beiträge
5
das ist auf alle Fälle schon mal ein guter Ansatz, danke! Performance sollte in dem Fall nicht das Problem sein, die Abfrage wird nur alle paar Wochen benötigt.

Das einzige Problem ist, dass ich nun für Kunden ohne Adresse keine Ausgabe bekomme statt der gewünschten NULL.
 

abenteurer

Benutzer
Beiträge
5
die letzte Lösung noch selbst gefunden: wenn ich die Einschränkung in den Join packe statt in die Where Klausel bekomme ich auch meine gewünschten NULL-Zeilen.
Dankeschön!

Wobei ich froh bin, dass es bei mir nur 3 Werte sind, die nacheinander abgefragt werden sollen und nicht 10....
 

ukulele

Datenbank-Guru
Beiträge
4.647
Ansonsten könnte man sich noch eine Sicht basteln die immer nur den "interessantesten" Datensatz liefert. Da gibt es sicher noch andere Ansatzmöglichkeiten. Auf jedenfall müsste man aber eine Art Funktion schreiben um die Wertigkeit zu ermitteln, ob das dann 3, 10 oder 100 Faktoren sind wäre egal :)
 

akretschmer

Datenbank-Guru
Beiträge
9.532
Ansonsten könnte man sich noch eine Sicht basteln die immer nur den "interessantesten" Datensatz liefert. Da gibt es sicher noch andere Ansatzmöglichkeiten. Auf jedenfall müsste man aber eine Art Funktion schreiben um die Wertigkeit zu ermitteln, ob das dann 3, 10 oder 100 Faktoren sind wäre egal :)

Da wir ja mit Datenbanken und Tabellen zu tun haben, denke ich, mit einer Tabelle die die Werte und Wertigkeiten beinhaltet wäre eine relativ dynamische Lösung machbar, die bei einer mehrstelligen Anzahl von Bedingungen noch immer lesbar bleibt...

Andreas
 

abenteurer

Benutzer
Beiträge
5
Ich komme mit der Abfrage so zwar hin, bin aber immer neugierig ;-)
Wie würde denn so eine Tabelle aussehen müssen, damit sie hinterher sinnvoll in die Abfrage eingebaut werden kann?
 
Werbung:

akretschmer

Datenbank-Guru
Beiträge
9.532
Ich komme mit der Abfrage so zwar hin, bin aber immer neugierig ;-)
Wie würde denn so eine Tabelle aussehen müssen, damit sie hinterher sinnvoll in die Abfrage eingebaut werden kann?

Gern doch, Lösung aber in PostgreSQL:

Also, ich habe Deine Tabellen und noch eine extra t3, welche in a Deine Adressart und in o die Wertung hat:

Code:
test=*# select * from t1;
 id | name
----+-------
  1 | name1
  2 | name2
  3 | name3
  4 | name4
(4 rows)

Time: 0,152 ms
test=*# select * from t2;
 id | kunde | adressart | str
----+-------+-----------+-----
  1 |     1 |         4 | xxx
  2 |     1 |         3 | yyy
  3 |     2 |         1 | zzz
  4 |     2 |         3 | aaa
  5 |     3 |         3 | bbb
(5 rows)

Time: 0,159 ms
test=*# select * from t3;
 a | o
---+---
 4 | 1
 1 | 2
 3 | 3
(3 rows)

Nun ein kleiner Zauberspruch:

Code:
test=*# select t1.name, foo.str from t1 left join (select *, row_number() over (partition by kunde order by o asc) from t2 left join t3 on t2.adressart=t3.a) foo on t1.id=foo.kunde and foo.row_number = 1;
 name  | str
-------+-----
 name1 | xxx
 name2 | zzz
 name3 | bbb
 name4 |
(4 rows)


Andreas
 
Oben