2011-09-21 22 views
16

Ho una domanda come questa:group_concat multiple su diversi campi utilizzando MySQL

SELECT product.id, 
     GROUP_CONCAT(image.id) AS images_id, 
     GROUP_CONCAT(image.title) AS images_title, 
     GROUP_CONCAT(facet.id) AS facets_id 
... 
GROUP BY product.id 

e la query funziona, ma non come previsto, perché se ho un prodotto con 5 sfaccettature e 1 immagine (supponiamo un'immagine con id = 7), quindi ottengo qualcosa di simile in "images_id":
"7,7,7,7,7"
Se ho 2 immagini (7 e 3), allora ottengo qualcosa del tipo:
"7,7,7,7,7,3,3,3,3,3"
e sfaccettature ottengo qualcosa di simile:
"8,7,6,5,4,8,7,6,5,4"

penso che MySQL sta facendo un certo tipo di unione delle differenti righe restituite dalla query e quindi concatenazione di tutto.

mio risultato atteso è (per l'ultimo esempio):

images_id = "7,3"
facets_id = "8,7,6,5,4"

posso ottenere che usando DISTINCT nel GROUP_CONCAT, ma poi ho un altro problema: Se ho due immagini con lo stesso titolo, una di queste è ommited, e poi ottengo qualcosa del tipo:
images_id = "7,3,5"
images_title = "Title7and3, Title5"

Quindi mi manca la relazione tra images_id e images_title.

Qualcuno sa se è possibile effettuare questa query in MySQL?

Forse sto complicando tutto senza alcun vantaggio reale. Sto provando a eseguire solo una query perché le prestazioni, ma ora non sono così sicuro se è ancora più veloce eseguire due query (una per selezionare le faccette e un'altra per le immagini per esempio).

Per favore, spieghi che cosa pensi sia la soluzione migliore per questo e perché.

Grazie!

risposta

8

Avrete bisogno di ottenere ogni gruppo separatamente:

SELECT 
    p.id, 
    images_id, 
    images_title, 
    facets_id, 
    ... 
FROM PRODUCT p 
JOIN (SELECT product.id, GROUP_CONCAT(image.id) AS images_id 
     FROM PRODUCT GROUP BY product.id) a on a.id = p.id 
JOIN (SELECT product.id, GROUP_CONCAT(image.title) AS images_title 
     FROM PRODUCT GROUP BY product.id) b on b.id = p.id 
JOIN (SELECT product.id, GROUP_CONCAT(facet.id) AS facets_id 
     FROM PRODUCT GROUP BY product.id) b on c.id = p.id 
... 
+0

Non capisco molto bene la query, ma sembra molto complessa, voglio dire, abbiamo bisogno di una sottoselezione con un gruppo per ogni concat? Sembra qualcosa di molto lento, non è più veloce 2 domande? – Enrique

+2

@Enrique, non si tratta di velocità, ma di correttezza. Se il mio codice non ha bisogno di funzionare effettivamente posso fare tutto all'istante. – Johan

+0

@Enrique, Non è necessaria una sottoselezione per ogni gruppo concat, solo per quelle tabelle in cui la corrispondenza con p.id restituisce più di 1 riga per p.id. – Johan

1

Se il problema è la velocità, allora può essere molto più veloce per semplicemente selezionare tutti i dati necessari, come righe separate, e fare il raggruppamento nella domanda, vale a dire:

SELECT product.id, image.id, image.title, facet.id 

Poi nell'applicazione:

foreach row: 
    push product_id onto list_of_product_ids 
    push image_id onto list_of_image_ids 
etc. 
30

Just add DISTINCT.

Esempio:
GROUP_CONCAT(DISTINCT image.id) AS images_id

+0

+1, Funziona anche per SQLite3 – user457015

+0

Penso che sia necessario approfondirlo. ''DISTINCT' => GROUP_CONCAT (DISTINCT image.id) AS images_id' non sembra essere la sintassi SQL e MySQL 5.1 genera un errore di sintassi. L'interrogante non ha menzionato alcun linguaggio di programmazione, quindi se questa risposta non è SQL, deve essere convertita o spiegata. – Animism

+0

Più 'GROUP_CONCAT's senza righe aggiuntive. +1 –

4

È possibile aggiungere solo la parola chiave DISTINCT, si otterrà i risultati desiderio.

SELECT tb_mod.*, tb_van.*, 
GROUP_CONCAT(DISTINCT tb_voil.vt_id) AS voil, 
GROUP_CONCAT(DISTINCT tb_other.oa_id) AS other, 
GROUP_CONCAT(DISTINCT tb_ref.rp_id) AS referral 
FROM cp_modules_record_tbl tb_mod 
LEFT JOIN cp_vane_police_tbl tb_van ON tb_van.mr_id= tb_mod.id 
LEFT JOIN cp_mod_voilt_tbl tb_voil ON tb_voil.mr_id= tb_mod.id 
LEFT JOIN cp_mod_otheraction_tbl tb_other ON tb_other.mr_id= tb_mod.id 
LEFT JOIN cp_mod_referral_tbl tb_ref ON tb_ref.mr_id= tb_mod.id 
WHERE tb_mod.mod_type = 2 GROUP BY tb_mod.id