Left Join -> Mehrfachauswahl bei Suche

ceverlante

Grünschnabel
Hallo Zusammen,

ich hab ein Problem, dass mir seit geraumer Zeit etwas Kopfzerbrechen macht.
Ich habe eine recht Umfangreiche Suche aufgebaut für ein Portal - in diesem Zuge soll der Besucher eine Agentur anhand seiner "Leistungen" (die die Agentur in mehrfach auswahl für sich getroffen hat) Auswählen können und entsprechend die Ergebnisse finden:

Als Beispiel
Ich Suche eine Agentur die Webdesign (id: 1) und gleichzeitig Grafikdesign (id:2) macht. Also soll bei der Suche nur die Agenturen gelistet werden, die auch diese Ausgewählt haben.

Hinweis
  • Es gibt eine "agenturen" Tabelle, wo alle allgemeinen Agentur Details stehen.
  • Dann gibt es eine agentur_dtls_leistungen Tabelle - die aber für die Abfrage nicht relevant ist. Hier sind quasi alle Leistungen gelistet
  • Und es gibt die Kombinations Tabelle agenturen_dtls_leistungen_comb die mit der agentur_id (sid von agentur) & der comb_id (sid von leistungen) verbunden sind

Den SQL Befehl habe ich wie folgt aufgebaut:
Code:
SELECT DISTINCT A.* 
FROM agenturen AS A 
INNER JOIN agenturen_dtls_leistungen_comb AS L 
ON (A.sid = L.agentur_id) 
WHERE status=1 
AND ( L.comb_id = 1 AND L.comb_id = 2 )

Code Info:
Um die Übersichtlichkeit zu lassen habe ich ein A.* genommen, aber ich Original Script nehme ich natürlich nur die Spalten die ich brauche. Das "status=1" nehme ich, weil die Abfrage Dynamisch aufgebaut wird.

Die Problemstellung
Das genaue Problem ist, wenn ich die "comb_id"s mit AND verknüpfe kommt als Ergebnis immer 0 Agenturen raus. Es funktioniert nur, wenn ich sie mit OR Verknüpfe - aber das ist ja dann
nicht das gewünschte Ergebnis. Wie bekomme ich es also jetzt hin, dass ich nur alle Agenturen bekomme die die zwei Leistungen Ausgewählt haben?

Ich wäre um konstruktive Hilfe sehr Dankbar.

Lieben Gruß,
ceverlante
 
Zuletzt bearbeitet:
Hi,

mach eine OR-Verknüpfung bzw. ein attribut IN (liste_der_leistungen), gruppiere nach Agentur und zähle die gefundenen Zeilen.

Zum Beispiel:
Code:
SELECT DISTINCT A.* 
   FROM agenturen AS A 
   INNER JOIN agenturen_dtls_leistungen_comb AS L 
      ON (A.sid = L.agentur_id) 
   WHERE status=1 
      AND L.comb_id IN (1, 2)
   GROUP BY A.sid
      HAVING COUNT(*) = 2

LG
 
Hallo kuddeldaddeldu,

danke für deine schnelle & konstruktive Antwort.

Das hat sogar soweit funktioniert. Nun stellt sich aber bei mir im gleichen Atemzug eine nächste Frage ein. Denn wie ich erwähnte wird die SQL Abfrage Dynamisch generiert und dies war nur ein "Teilstück" des Codes. Wenn ich jetzt NUR nach Leistungen suche - funktioniert es super. Das gleiche Spielchen gibt es aber jetzt auch für Branchen. Dieser können in der Suche natürlich auch Kombiniert werden mit den Leistungen. Dort sehe ich das Problem bei der Zeile

Code:
GROUP BY A.sid
      HAVING COUNT(*) = 2

Wie folgt sieht jetzt mein umgeschriebener Code aus:

Code:
SELECT DISTINCT A.* 
FROM agenturen AS A 
INNER JOIN agenturen_dtls_branchenerfahrung_comb 
AS B ON (A.sid = B.agentur_id) 
INNER JOIN agenturen_dtls_leistungen_comb 
AS L ON (A.sid = L.agentur_id) 
WHERE status=1 
AND L.comb_id IN ( 13, 15, 16) 
AND B.comb_id IN ( 6, 7, 8)
GROUP BY A.sid
HAVING COUNT(L.comb_id) = 3

Müsste ich denn hier nicht auch noch die B.comb_id per HAVING COUNT Gruppieren? Falls ja, wie sollte das als Select auschauen, oder verstehe ich da irgendwas falsch?

Vielen Dank schon mal im Voraus.

Lieben Gruß,
ceverlante
 
Hi
So mal auf die Schnelle:

du hast folgenden Input:
$1=LeistungsID1
$2=LeistungsID2
$3=Anzahl Leistungen die min. vorhanden sein müssen
$4=BraunchenID1
$5=BraunchenID2
$6=Anzahl Branchen die min. vorhanden sein müssen
Dann setzt du deine Variablen wie folgt im SQL:
SQL:
#Tabellennamen sowie Verknüpfungen kannst du ja dann selbst setzen
select * from argentur as a
left join argentur_leistung as al on al.fs_argentur=a.id and (al.fs_leistung=$1 or al.fs_leistung=$2)
left join argentur_branche as ab on ab.fs_argentur=a.id and (ab.fs_branche=$4 or al.fs_branche=$5)
group by a.id
having count(al.id)>$3 and count(ab.id)>$6
Voraussetzung ist natürlich, dass eine Verknüpfung in argentur_leistung nicht zweimal vorkommen kann ;)

Gruss
 
Zuletzt bearbeitet:
Hi,

das stimmt so noch nicht. Die Joins liefern ja alle möglichen Kombinationen. Dementsprechend sind count(al.id) und count(ab.id) immer gleich, und zwar gleich der Anzahl gefundener Kombinationen. Wenn jetzt also 3 Leistungen und 2 Branchenerfahrungen gefordert sind, eine Agentur aber nur 2 der Leistungen und beide Branchenerfahrungen bietet, wären beide HAVING-Bedingungen erfüllt, da es 4 Kombinationen gibt.

Die Anzahl gefundener Kombinationen muss also gleich anzahl_leistungen * anzahl_branchen sein, in Deinem Beispiel:

Code:
SELECT A.* FROM agenturen AS A 
   INNER JOIN agenturen_dtls_branchenerfahrung_comb AS B 
      ON (A.sid = B.agentur_id) 
   INNER JOIN agenturen_dtls_leistungen_comb AS L 
      ON (A.sid = L.agentur_id) 
   WHERE status=1 
      AND L.comb_id IN ( 13, 15, 16) 
      AND B.comb_id IN ( 6, 7, 8)
   GROUP BY A.sid
      HAVING COUNT(A.sid) = 9

LG
 
Hi

Wenn jetzt also 3 Leistungen und 2 Branchenerfahrungen gefordert sind, eine Agentur aber nur 2 der Leistungen und beide Branchenerfahrungen bietet, wären beide HAVING-Bedingungen erfüllt, da es 4 Kombinationen gibt.
Du hast recht, wenn man allerdings nur die eindeutigen IDs zählt sollte es aufgehen:
SQL:
HAVING count(distinct al.id)>$3 AND count(distinct ab.id)>$6

count(distinct al.id) ist nun also immer gleich der Anzahl wirklicher argentur_leistung-Verknüpfungen.

Gruss
 

Neue Beiträge

Zurück