web-dev-qa-db-fra.com

SQL SELECT un à plusieurs en une seule ligne

J'ai des données dans deux tableaux.

La première table a une clé primaire appelée PKID

PKID  DATA
0    myData0
1    myData1
2    myData2

La deuxième table a la colonne PKID du tableau 1 comme clé étrangère

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

L'instruction SELECT de base que je fais maintenant est

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

Cela produit un tableau comme celui-ci:

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

Ce que je voudrais, c'est le tableau suivant:

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

Si cela peut aider, chaque PKID aura exactement 3 entrées dans le tableau 2.

Est-ce que quelque chose comme ça est possible dans MySQL?

24
Grizz

C'est une façon d'obtenir le résultat.

Cette approche utilise des sous-requêtes corrélées. Chaque sous-requête utilise un ORDER BY clause pour trier les lignes associées de table2 et utilise la clause LIMIT pour récupérer les 1ère, 2e et 3e lignes.

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  

SUIVRE

@ gliese581g souligne qu'il peut y avoir des problèmes de performances avec cette approche, avec un grand nombre de lignes retournées par la requête externe, car chaque sous-requête de la liste SELECT est exécutée pour chaque ligne retournée dans la requête externe.

Il va sans dire que cette approche réclame un indice:

ON table2 (PKID_FROM_TABLE_1, U_DATA)

-ou, au minimum-

ON table2 (PKID_FROM_TABLE_1)

Il est probable que ce dernier index existe déjà, si une clé étrangère est définie. L'ancien index permettrait à la requête d'être entièrement satisfaite à partir des pages d'index ("Utilisation de l'index"), sans avoir besoin d'une opération de tri ("Utilisation du tri de fichiers").

@ glies581g a tout à fait raison de souligner que les performances de cette approche peuvent être problématiques sur les "grands" ensembles.

19
spencer7593

Selon votre version de MySQL, vous pouvez consulter GROUP_CONCAT

8
sdfor