J'ai une requête MySQL dans laquelle je veux inclure une liste d'ID d'une autre table. Sur le site Web, les utilisateurs peuvent ajouter certains éléments, puis les ajouter à leurs favoris. Je veux essentiellement obtenir la liste des pièces d'identité des personnes qui ont mis en favoris cet élément (c'est un peu simplifié, mais c'est à cela qu'il se résume).
Fondamentalement, je fais quelque chose comme ça:
SELECT *,
GROUP_CONCAT((SELECT userid FROM favourites WHERE itemid = items.id) SEPARATOR ',') AS idlist
FROM items
WHERE id = $someid
De cette façon, je serais en mesure de montrer qui a favorisé certains éléments, en divisant la liste d'id plus tard en un tableau dans PHP plus loin dans mon code, mais j'obtiens l'erreur MySQL suivante:
1242 - La sous-requête renvoie plus d'une ligne
Je pensais que c'était un peu l'intérêt d'utiliser GROUP_CONCAT
au lieu de, par exemple, CONCAT
? Suis-je en train de mal faire ça?
Ok, merci pour les réponses jusqu'à présent, cela semble fonctionner. Cependant, il y a un hic. Les éléments sont également considérés comme favoris s'ils ont été ajoutés par cet utilisateur. J'aurais donc besoin d'une vérification supplémentaire pour vérifier si creator = userid. Quelqu'un peut-il m'aider à trouver un moyen intelligent (et, espérons-le, efficace) de le faire?
Je vous remercie!
Edit: je viens d'essayer de faire ceci:
SELECT [...] LEFT JOIN favourites ON (userid = itemid OR creator = userid)
Et idlist est vide. Notez que si j'utilise INNER JOIN
au lieu de LEFT JOIN
J'obtiens un résultat vide. Même si je suis sûr qu'il existe des lignes qui répondent à l'exigence ON.
Vous ne pouvez pas accéder aux variables de la portée externe dans de telles requêtes (vous ne pouvez pas utiliser items.id
Là). Vous devriez plutôt essayer quelque chose comme
SELECT
items.name,
items.color,
CONCAT(favourites.userid) as idlist
FROM
items
INNER JOIN favourites ON items.id = favourites.itemid
WHERE
items.id = $someid
GROUP BY
items.name,
items.color;
Développez la liste des champs selon vos besoins (nom, couleur ...).
OP a presque raison. GROUP_CONCAT
devrait encapsuler les colonnes dans la sous-requête et non la sous-requête complète (j'écarte le séparateur car la virgule est la valeur par défaut):
SELECT i.*,
(SELECT GROUP_CONCAT(userid) FROM favourites f WHERE f.itemid = i.id) AS idlist
FROM items i
WHERE i.id = $someid
Cela donnera le résultat souhaité et signifie également que la réponse acceptée est partiellement fausse, car vous pouvez accéder aux variables de portée externe dans une sous-requête.
Je pense que vous pouvez avoir le "userid = itemid" mal, ne devrait-il pas être comme ceci:
SELECT ITEMS.id,GROUP_CONCAT(FAVOURITES.UserId) AS IdList
FROM FAVOURITES
INNER JOIN ITEMS ON (ITEMS.Id = FAVOURITES.ItemId OR FAVOURITES.UserId = ITEMS.Creator)
WHERE ITEMS.Id = $someid
GROUP BY ITEMS.ID
Oui, la solution de soulmerge est correcte. Mais j'avais besoin d'une requête où je devais collecter des données à partir de plusieurs tables enfants, par exemple:
Chaque session a plus de lignes dans les tables des tables enfants (plus de calendriers, plus d'accessoires)
Et je devais rassembler dans une collection pour chaque session à afficher dans la ligne de minerai (certains d'entre eux):
session_id | session_name | date | time_start | time_end | accessories | presenters
Ma solution (après plusieurs heures d'expériences):
SELECT sessions.uid, sessions.name,
,(SELECT GROUP_CONCAT( `events`.date SEPARATOR '</li><li>')
FROM `events`
WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS date
,(SELECT GROUP_CONCAT( `events`.time_start SEPARATOR '</li><li>')
FROM `events`
WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS time_start
,(SELECT GROUP_CONCAT( `events`.time_end SEPARATOR '</li><li>')
FROM `events`
WHERE `events`.session_id = sessions.uid ORDER BY `events`.date) AS time_end
,(SELECT GROUP_CONCAT( accessories.name SEPARATOR '</li><li>')
FROM accessories
WHERE accessories.session_id = sessions.uid ORDER BY accessories.name) AS accessories
,(SELECT GROUP_CONCAT( presenters.name SEPARATOR '</li><li>')
FROM presenters
WHERE presenters.session_id = sessions.uid ORDER BY presenters.name) AS presenters
FROM sessions
Donc pas besoin de JOIN ou GROUP BY. Une autre chose utile pour afficher des données conviviales (lors de leur "écho"):
J'espère que ça aidera quelqu'un. À votre santé!
Le but de GROUP_CONCAT est correct mais la sous-requête n'est pas nécessaire et provoque le problème. Essayez plutôt ceci:
SELECT ITEMS.id,GROUP_CONCAT(FAVOURITES.UserId)
FROM FAVOURITES INNER JOIN ITEMS ON ITEMS.Id = FAVOURITES.ItemId
WHERE ITEMS.Id = $someid
GROUP BY ITEMS.ID