Utilizzando GROUP_CONCAT su sottoquery in MySQL
-
22-08-2019 - |
Domanda
Ho una query MySQL in cui voglio includere un elenco di ID di un'altra tabella.Sul sito, le persone sono in grado di aggiungere alcuni elementi, e poi aggiungere gli elementi per i loro favoriti.Io, fondamentalmente, vuole ottenere l'elenco di ID di persone che hanno favoriti elemento (questo è un po ' semplificato, ma questo è quello che si riduce a).
Fondamentalmente, io faccio qualcosa di simile a questo:
SELECT *,
GROUP_CONCAT((SELECT userid FROM favourites WHERE itemid = items.id) SEPARATOR ',') AS idlist
FROM items
WHERE id = $someid
In questo modo, vorrei essere in grado di dimostrare che è piaciuto qualche elemento, suddividendo la idlist in seguito a un array in PHP ulteriormente nel mio codice, ma ricevo il seguente errore MySQL:
1242 - Subquery restituisce più di 1 riga
Ho pensato che era una sorta di punto di utilizzo GROUP_CONCAT
invece di, per esempio, CONCAT
?Sto andando su questa strada sbagliata?
Ok, grazie per le risposte finora, che sembra funzionare.Tuttavia, vi è una cattura.Gli elementi sono considerati essere preferito se è stato aggiunto dall'utente.Quindi avrei bisogno di un ulteriore controllo per verificare se il creatore = userid.Qualcuno può aiutarmi a trovare una smart (e, si spera, efficace modo per fare questo?
Grazie!
Edit:Ho appena provato a fare questo:
SELECT [...] LEFT JOIN favourites ON (userid = itemid OR creator = userid)
E idlist è vuota.Nota che se uso INNER JOIN
invece di LEFT JOIN
Ottengo un risultato vuoto.Anche se sono sicuro che ci sono delle righe che soddisfano il requisito.
Soluzione
Non si può accedere alle variabili nel perimetro esterno tali query (non può usare items.id
lì). Si dovrebbe piuttosto provare qualcosa di simile
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;
Espandere l'elenco dei campi in base alle esigenze (nome, colore ...).
Altri suggerimenti
OP quasi capito bene. GROUP_CONCAT
dovrebbe essere avvolgendo le colonne della subquery e non il completa sottoquery (sto respingendo il separatore perché virgola è il valore predefinito ):
SELECT i.*,
(SELECT GROUP_CONCAT(userid) FROM favourites f WHERE f.itemid = i.id) AS idlist
FROM items i
WHERE i.id = $someid
Questo produrrà il risultato desiderato e significa anche che la risposta accettata è parzialmente sbagliata, perché si può accedere alle variabili ambito esterno in una sottoquery.
Credo che si può avere il "userid = Itemid" sbagliato, non dovrebbe essere in questo modo:
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
Lo scopo di group_concat è corretto ma la subquery è inutile e causa il problema. Prova a modificare:
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
Sì, soulmerge la soluzione è ok.Ma ho bisogno di una query in cui ho dovuto raccogliere dati da più tabelle figlio, per esempio:
- la tabella principale: le sessioni di (sessioni di presentazione) (id, nome, ..)
- 1 ° bambino da tabella: eventi con chiave session_id (uid, session_uid, data, time_start, time_end)
- 2 ° bambino tabella: accessories_needed (computer portatile, proiettore, microfoni, etc.) con chiave session_id (uid, session_uid, accessory_name)
- 3 ° bambino tabella: session_presenters (relatore persone) con chiave session_id (uid, session_uid, presenter_name, indirizzo...)
Ogni Sessione ha più righe nel bambino tabelle (più tempi, più accessori)
E ho bisogno di raccogliere in una collezione per ogni sessione per visualizzare in ore di fila (alcuni di loro):
session_id | session_name | date | time_start | time_end | accessories | presenters
La mia soluzione (dopo molte ore di esperimenti):
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
Quindi non PARTECIPARE o di GRUPPO necessari.Un'altra cosa utile per visualizzare i dati amichevole (quando "eco" di loro):
- si può avvolgere gli eventi.data, time_start, time_end, ecc. "<UL><LI> ...</LI></UL>"così il "<LI></LI>"utilizzato come separatore di query i risultati in un elenco di elementi.
Spero che questo aiuta qualcuno.Evviva!