2016-10-04 2 views
2

Ich habe Tabellen mit einer zu vielen Beziehung.MySQL JOIN Abfrage mit nur einem von mehreren spezifischen Werten

rental 
------ 
id 
book_date 

prices 
------ 
rental_id 
type_id 
value 

Eine normale JOIN Abfrage würde Ergebnisse

select * from rental a join prices b on a.id = b.rental_id; 

id book_date rental_id type_id value 

1, 2016-10-04, 1,  8,  200 
1, 2016-10-04, 1,  10,  300 
2, 2016-10-04, 2,  8,  250 
3, 2016-10-04, 3,  8,  200 
3, 2016-10-04, 3,  10,  300 

, was ich will, ist, wenn Preisrekordler = 10 type_id hat, dann diese Zeile nehmen; Wenn dies nicht der Fall ist, wird die Zeile mit type_id = 8 verwendet. Das Ergebnis Ich möchte:

1 2016-10-04 1 10 300 
2 2016-10-04 2  8 250 
3 2016-10-04 3 10 300 

ich diese Frage haben, aber es scheint nicht auf meinem Fall zu arbeiten:

select * from rental a 
join prices b 
on a.id = b.rental_id and 
     (if(b.type_id = 10, b.type_id = 10, b.type_id = 8)) 
ORDER BY a.id DESC LIMIT 20 

Antwort

1

, was ich will, ist, wenn Preisrekordler = 10 type_id hat dann ist es nur verbinden mit type_id 10, wenn nicht, es ist mit type_id verbinden = 8

Das bedeutet, dass der Datensatz mit type_id 8 verworfen, wenn es mit type_id 10. Das „andere“ Anrufe für eine andere JOIN JOIN ein LEFT tatsächlich da der Datensatz könnte zu andere Datensatz ist im Vergleich nicht vorhanden:

SELECT a.*, b.* FROM rental a 
JOIN prices b ON (a.id = b.rental_id) 
LEFT JOIN prices check ON (a.id = check.rental_id AND check.type_id = 10) 

WHERE b.type_id = 10 OR (b.type_id = 8 AND check.type_id IS NULL) 

Dies bedeutet, dass der JOIN alle Typ 8 und Typ 10 bekommt; dann JOIN die LINKE wird es nur machen, so werden die Art 8er genommen, wenn es keine entsprechenden Typ 10:

 1 10 10 
     2 8 10  # discarded 
     2 10 10 
     3 8 NULL 
     4 15 NULL # discarded 
     4 8 NULL 

ID 1 nur 10 Datensatz hat, ist es sowohl Abfrage abgerufen werden, und es wird akzeptiert. ID 2 hat beides, also wird der 8-10-Datensatz verworfen, weil b-Typ 8 ist, aber c-Typ ist nicht NULL. ID 3 hat nur einen Datensatz von 8, daher gibt der 10 suchende LEFT JOIN NULL zurück, der zum zweiten Teil des OR passt. ID 4 hat type_ids 8 und 15, und die 15 wird von beiden Teilen des OR verworfen.

+0

danke, es funktioniert auf meinem Fall. –

1

wenn Preisrekordler 10 type_id hat = dann ist es nur mit type_id 10, verbinden wenn nicht ist es mit type_id beitreten = 8

Diese Logik kann für jeden rental_id, indem sie den Datensatz mit der maximalen type_id erzwungen werden. Wenn ja, dann können Sie einfach eine dritte Join-Bedingung hinzuzufügen, die die Ergebnismenge auf Datensätze beschränken wird diese zusätzliche Bedingung erfüllen:

SELECT a.*, b.* 
FROM rental a 
INNER JOIN prices b 
    ON a.id = b.rental_id 
INNER JOIN 
(
    SELECT rental_id, 
      CASE WHEN MAX(CASE WHEN type_id = 10 THEN 1 END) = 1 THEN 10 
       WHEN MAX(CASE WHEN type_id = 8 THEN 1 END) = 1 THEN 8 
       ELSE MAX(type_id) 
      END AS type_id 
    FROM prices 
    GROUP BY rental_id 
) c 
    ON b.rental_id = c.rental_id AND 
     b.type_id = c.type_id 

Folgen Sie dem Link unten für eine laufende Demo:

SQLFiddle

+0

Sorry vergessen zu erwähnen, eigentlich 10 ist nicht das Maximum von type_id, es gibt mehrere größere Nummern als 10. Also ich denke ich kann das Maximum nicht zur Auswahl verwenden. Wenn 10 vorhanden ist, verwende 10, wenn nicht, verwende stattdessen 8. Danke :) –