37 Stimmen

One-to-Many SQL SELECT in eine einzelne Zeile

Ich habe Daten in zwei Tabellen.

Die erste Tabelle hat einen Primärschlüssel namens PKID

PKID  DATA
0    myData0
1    myData1
2    myData2

Die zweite Tabelle hat die Spalte PKID aus Tabelle 1 als Fremdschlüssel

PKID_FROM_TABLE_1  U_DATA
       0          unique0
       0          unique1        
       0          unique2
       1          unique3
       1          unique4
       1          unique5
       2          unique6
       2          unique7
       2          unique8

Die grundlegende SELECT-Anweisung, die ich jetzt mache, lautet

SELECT a.PKID, a.DATA, b.U_DATA
FROM table1 as a
INNER JOIN table2 as b
ON a.PKID = b.PKID_FROM_TABLE_1

Das Ergebnis ist eine Tabelle wie diese:

PKID   DATA     U_DATA
 0   myData0    unique0
 0   myData0    unique1
 0   myData0    unique2
 1   myData1    unique3
 1   myData1    unique4
 1   myData1    unique5
 2   myData2    unique6
 2   myData2    unique7
 2   myData2    unique8

Ich hätte gerne die folgende Tabelle:

PKID   DATA    U_DATA1    U_DATA2    U_DATA3
 0     myData0 unique0    unidque1   unique2
 1     myData1 unique3    unidque4   unique5
 2     myData2 unique6    unidque7   unique8

Wenn es hilft, wird jede PKID genau 3 Einträge in Tabelle2 haben.

Ist so etwas in MySQL möglich?

24voto

spencer7593 Punkte 103188

Dies ist eine Möglichkeit, das Ergebnis zu erhalten.

Bei diesem Ansatz werden korrelierte Unterabfragen verwendet. Jede Unterabfrage verwendet eine ORDER BY Klausel, um die verwandten Zeilen aus Tabelle2 zu sortieren, und verwendet die LIMIT Klausel, um die Zeilen 1, 2 und 3 abzurufen.

SELECT a.PKID
     , a.DATA
     , (SELECT b1.U_DATA FROM table2 b1
         WHERE b1.PKID_FROM_TABLE_1 = a.PKID 
         ORDER BY b1.U_DATA LIMIT 0,1
       ) AS U_DATA1
     , (SELECT b2.U_DATA FROM table2 b2
         WHERE b2.PKID_FROM_TABLE_1 = a.PKID 
         ORDER BY b2.U_DATA LIMIT 1,1
       ) AS U_DATA2
     , (SELECT b3.U_DATA FROM table2 b3
         WHERE b3.PKID_FROM_TABLE_1 = a.PKID 
         ORDER BY b3.U_DATA LIMIT 2,1
       ) AS U_DATA3
  FROM table1 a
 ORDER BY a.PKID  

FOLLOWUP

@gliese581g weist darauf hin, dass es bei diesem Ansatz zu Leistungsproblemen kommen kann, wenn die äußere Abfrage eine große Anzahl von Zeilen zurückgibt, da jede Unterabfrage in der SELECT-Liste für jede in der äußeren Abfrage zurückgegebene Zeile ausgeführt wird.

Es sollte selbstverständlich sein, dass dieser Ansatz nach einem Index schreit:

ON table2 (PKID_FROM_TABLE_1, U_DATA)

-oder zumindest-

ON table2 (PKID_FROM_TABLE_1)

Es ist wahrscheinlich, dass der letztere Index bereits existiert, wenn ein Fremdschlüssel definiert ist. Der erste Index würde es ermöglichen, die Abfrage vollständig aus den Indexseiten zu erfüllen ("Using index"), ohne dass eine Sortieroperation erforderlich ist ("Using filesort").

@glies581g hat Recht, wenn er darauf hinweist, dass die Leistung dieses Ansatzes bei "großen" Mengen problematisch sein kann.

21voto

sdfor Punkte 6044

Abhängig von Ihrer MySQL-Version können Sie GROUP_CONCAT untersuchen

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X