SQL Abfrage mehrere Tabellen, mit mehreren Joins und Spalte Feld mit durch Komma getrennte Liste

8

Ich habe eine Abfrage, wo ich drei separate Tabellen (Knoten, Kontrolle, Service) beitreten.

Im Folgenden finden Sie die Spaltenüberschriften und Beispieldaten.

%Vor%

Wie Sie sehen, haben die Datenbanktabellen mit Ausnahme der Spalte node.serviceID eine gewisse Normalisierung. Ich stimme ganz von ganzem Herzen zu, dass node.serviceID normalisiert und eine Pivot-Tabelle von Eins-zu-Vielen erstellt werden sollte. Kein Argument dort. Ich kontrolliere jedoch nicht die Skripte, die die Informationen in die Datenbank einfügen. Ich kann nur aus den Tabellen lesen und die Daten formatieren, wie ich kann.

Also, unten ist die SQL-Abfrage, die ich schrieb, die funktioniert, aber die, wie erwartet, node.serviceID passt nicht gut zu service.serviceID . Bitte beachten Sie, dass ich in meiner letzten Abfrage kein SELECT * verwende. Ich wähle etwa 20 Felder aus der Knotentabelle aus und möchte die Abfrage nicht verwirrender machen. Unten ist nur ein Beispiel.

%Vor%

Die obige Abfrage spuckt etwas ähnliches aus:

%Vor%

Nach was ich suche ist das:

%Vor%

Ich habe stackoverflow.com für jemanden mit einem Problem wie diesem durchforstet, aber ich kann nur entweder mehrere Tabellen über ID und Namen finden ODER jemanden, der eine Liste von IDs erweitert, aber nicht beides zusammen.

Dieser kam in der Nähe: Mit ID, die Komma getrennt sind sql aber nicht ganz.

Ich habe verschiedene Methoden von CFML mit ListToArray () ausprobiert und versucht, sie mit einem Index zu durchlaufen, aber nichts würde für mich funktionieren.

Der Server, auf dem ich die Daten erhalte, ist MySQL 5.1, und ich verwende eine Kombination aus jQuery und ColdFusion (Railo 4.2), um die Daten zu formatieren.

Dies ist das erste Mal, dass ich auf stackoverflow poste, also entschuldige ich mich, wenn es wirklich eine Antwort darauf gibt, ich habe nicht lange genug gesucht und würde diese Frage zu einem Duplikat machen.

----------------- UPDATE --------------------

Ich habe versucht, die Abfrage und CFML von Leigh vorgeschlagen.

Also, ich bekomme Folgendes:

server1 Dienstname Eins, Dienstname Eins, Dienstname Eins, Dienstname Eins, Dienstname Eins, Dienstname Eins, Dienstname Eins, Dienstname Zwei, Dienstname Zwei, Dienstname Zwei, Dienstname Zwei, Dienstname Zwei, Dienstname zwei, Dienstname drei, Dienstname vier, Dienstname vier, Dienstname vier, Dienstname vier, Dienstname vier, Dienstname vier, Dienstname vier

Ich bin mir nicht sicher, ob das an der CFML oder etwas in der SQL-Abfrage nur ein bisschen Veränderung ist. Aber es sieht vielversprechend aus.

    
Grimdari 21.08.2014, 23:54
quelle

1 Antwort

5

Wenn Sie die Tabellenstruktur wirklich nicht ändern können, ist wahrscheinlich das Beste, was Sie tun können, einer der alten Listen-Hacks:

  • Verwenden Sie JOIN mit FIND_IN_SET (Wert, KommaSepariertString )

    SELECT n.Host, c.Name AS ControlName, s.Name AS ServiceName FROM node n LEFT JOIN control c ON c.controlID = n.controlID LEFT JOIN service s ON FIND_IN_SET(s.serviceID, n.serviceId) ORDER BY n.host, s.Name ;

  • Verwenden Sie LIKE , um das Vorhandensein eines bestimmten serviceID-Werts in der Knotenliste zu erkennen

    SELECT n.Host, c.Name AS ControlName, s.Name AS ServiceName FROM node n LEFT JOIN control c ON c.controlID = n.controlID LEFT JOIN service s ON CONCAT(',', n.serviceID,',') LIKE CONCAT('%,', s.serviceID,',%') ORDER BY n.host, s.Name ;

SQLFiddle

Wie Sie bereits bemerkt haben, sollte diese Spalte jedoch normalisiert werden. Während die obigen Methoden für kleine Datensätze funktionieren sollten, leiden sie unter den üblichen Problemen beim Arbeiten mit "Listen". Keine der Methoden ist sehr indexfreundlich und wird daher nicht gut skalieren. Beide führen auch Zeichenfolgenvergleiche durch. Daher kann der geringste Unterschied dazu führen, dass der Abgleich fehlschlägt. Zum Beispiel würde 1,4 zwei Service-IDs entsprechen, während 1,(space)4 oder 1,4.0 nur einer entsprechen würde.

Aktualisierung basierend auf Kommentaren:

Beim zweiten Lesen bin ich mir nicht sicher, ob das Obige die genaue Frage beantwortet, die Sie stellen, aber es sollte eine gute Grundlage für die Arbeit mit ... bieten.

Wenn Sie keine CSV-Liste mehr wünschen, verwenden Sie einfach eine der obigen Abfragen und geben Sie die einzelnen Abfrage-Spalten wie gewohnt aus. Das Ergebnis ist ein Servicename pro Zeile, dh:

%Vor%

Wenn Sie andernfalls die durch Kommas getrennten Werte beibehalten möchten, können Sie in den Abfrageergebnissen eine <cfoutput group=".."> verwenden. Da die Ergebnisse zuerst von "Host" geordnet werden, so etwas wie der Code unten. Hinweis: Damit "Gruppe" ordnungsgemäß funktioniert, müssen die Ergebnisse nach Host geordnet sein und Sie müssen mehrere cfoutput -Tags verwenden, wie unten gezeigt.

%Vor%

Das Ergebnis sollte so aussehen:

%Vor%


Update 2:

Ich habe vergessen, dass es in MySQL eine einfachere Alternative zu cfoutput group gibt: GROUP_CONCAT

%Vor%     
Leigh 22.08.2014, 00:31
quelle

Tags und Links