2017-09-10 4 views
0

Ich habe eine Haupttabelle mit der Bezeichnung Lieferungen und eine Beziehung zwischen eins und vielen mit delivery_languages ​​als dl, deliveries_markets dm und deliveries_tags dt mit delivery_id als Fremdschlüssel. Diese 3 Tabellen stehen jeweils eins zu eins mit Sprachen, Märkten und Tags. Zusätzlich haben Lieferungen, Tabelle eine Eins-zu-eins-Beziehung zu Unternehmen und haben company_is als Fremdschlüssel. Es folgt eine Abfrage, die ich geschrieben habe:Abrufen bestimmter Zeilen aus mehreren Joins SQL

SELECT deliveries.*, languages.display_name, markets.default_name, tags.default_name, companies.name 
FROM deliveries 
JOIN deliveries_languages dl ON dl.delivery_id = deliveries.id 
JOIN deliveries_markets dm ON dm.delivery_id = deliveries.id 
JOIN deliveries_tags dt ON dt.delivery_id = deliveries.id 
JOIN languages ON languages.id = dl.language_id 
JOIN markets ON markets.id = dm.market_id 
JOIN tags ON tags.id = dt.tag_id 
JOIN companies ON companies.id = deliveries.company_id 
WHERE 
deliveries.name ILIKE '%new%' AND 
deliveries.created_by = '5f331347-fb58-4f63-bcf0-702f132f97c5' AND 
deliveries.deleted_at IS NULL 
LIMIT 10 

Hier bin ich immer redundante delivery_ids weil für jede delivery_id gibt es mehrere Sprachen, Märkte und Tags. Ich möchte limit für verschiedene delivery_ids verwenden. Also, Limit 10 sollte mir nicht 10 Datensätze von oben Join-Abfrage aber 10 Datensätze geben, wo es eine eindeutige delivery_id (deliveries.id) gibt. Ich kann wahrscheinlich abgeleitetes Tabellenkonzept hier verwenden, aber ich bin nicht sicher, wie ich das tun kann. Kann mir bitte jemand helfen, dieses Problem zu lösen.

+0

Welche DBMS verwenden Sie? – jarlh

+0

Wie wählt man diese 10 Zeilen pro Zustellungs-ID aus? (Mehrere Sprachen zu behalten, scheint etwas merkwürdig.) – jarlh

+0

Ich benutze postgreSQL –

Antwort

0

In Postgres können Sie distinct on verwenden:

SELECT DISTINCT ON (d.id) d.*, l.display_name, m.default_name, t.default_name, c.name 
FROM deliveries d JOIN 
    deliveries_languages dl 
    ON dl.delivery_id = d.id JOIN 
    deliveries_markets dm 
    ON dm.delivery_id = d.id JOIN 
    deliveries_tags dt 
    ON dt.delivery_id = d.id JOIN 
    languages l 
    ON l.id = dl.language_id JOIN 
    markets m 
    ON m.id = dm.market_id JOIN 
    tags 
    ON t.id = dt.tag_id JOIN 
    companies c 
    ON c.id = d.company_id 
WHERE d.name ILIKE '%new%' AND 
     d.created_by = '5f331347-fb58-4f63-bcf0-702f132f97c5' AND 
     d.deleted_at IS NULL 
ORDER BY d.id 
LIMIT 10; 

Für größere Datenmengen, kann dies sehr ineffizient sein. Multiple Junction-Tabellen ergeben kartesische Produkte, wenn sie so verwendet werden. Für eine kleine Menge von Daten sollte dies jedoch Ihr Problem lösen.

+0

Das funktioniert für mich. Aber Sie sagten, die Aufführung würde behindern. Liegt es an mehreren Joins oder an der DISTINCT ON-Klausel? Ist es auch effizienter als die Verwendung von Unterabfragen? –

+0

Vielen Dank Gordon Linoff –

+0

@NilakshiNaphade. . . Das liegt daran, dass die Joins ein kartesisches Produkt in verschiedenen Dimensionen erzeugen. . . Für eine gegebene Lieferung sind die Zwischenergebnisse die Anzahl der Sprachen multipliziert mit der Anzahl der Märkte multipliziert mit der Anzahl der Tags. –

Verwandte Themen