question GROUP_CONCAT et LEFT_JOIN - Toutes les lignes retournées
-
11-09-2019 - |
Question
Disons que mon schéma DB est la suivante:
T_PRODUCT
id_product (int, primary)
two entries: (id_product =1) , (id_product =2)
T_USER
id_user (int, primary)
id_product (int, foreign key)
name_user (varchar)
two entries: (id_product=1,name_user='John') , (id_product=1,name_user='Mike')
Si je lance une première requête pour obtenir tous les produits avec leurs utilisateurs (s'il y en a), je reçois ceci:
SELECT T_PRODUCT.id_product, T_USER.name_user
FROM T_PRODUCT
LEFT JOIN T_USER on T_USER.id_product = T_PRODUCT.id_product;
>>
id_product name_user
1 John
1 Mike
2 NULL
me semble bon. Maintenant, si je veux la même chose, sauf que je voudrais avoir un produit par ligne, avec les noms d'utilisateur concaténés (s'il y a des utilisateurs, sinon NULL):
SELECT T_PRODUCT.id_product, GROUP_CONCAT(T_USER.name_user)
FROM T_PRODUCT
LEFT JOIN T_USER on T_USER.id_product = T_PRODUCT.id_product;
>>
id_product name_user
1 John,Mike
**expected output**:
id_product name_user
1 John,Mike
2 NULL
S'il n'y a pas d'utilisateurs pour un produit, le GROUP_CONCAT empêche mysql de produire une ligne pour ce produit, même si il y a un LEFT JOIN .
- Est-ce un comportement MySQL attendu?
- Est-il possible que je pourrais obtenir le résultat attendu en utilisant GROUP_CONCAT ou une autre fonction?
La solution
Ah, trouvé ma réponse:
Vous ne devriez jamais oublier le GROUP BY clause lorsque vous travaillez avec GROUP_CONCAT .
Je manquais GROUP BY T_PRODUCT.id_product
dans ma deuxième requête.
Je vais laisser la question en cas où quelqu'un est aussi distrait que je suis.
Modifier :
De cette réponse, je me suis dit que je peux aussi activer le mode SQL ONLY_FULL_GROUP_BY
pour forcer MySQL à lancer une erreur dans le cas où le GROUP BY est manquant ou incorrect.
Autres conseils
Alternativement, vous pouvez utiliser un sous-requête, essai juste pour la performance
SELECT
T_PRODUCT.id_product,
(SELECT GROUP_CONCAT(T_USER.name_user)
FROM T_USER
WHERE T_USER.id_product = T_PRODUCT.id_product
)
FROM T_PRODUCT