2011-09-21 83 views
16

tengo una consulta como esta:GROUP_CONCAT múltiple en diferentes campos usando 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 

Y funciona la consulta, pero no como se esperaba, ya que si tengo un producto con 5 facetas y la imagen 1 (supongamos una imagen con id = 7), entonces obtengo algo como esto en "images_id":
"7,7,7,7,7"
Si tengo 2 imágenes (7 y 3), entonces obtengo algo así como:
"7,7,7,7,7,3,3,3,3,3"
y en facetas me sale algo como:
"8,7,6,5,4,8,7,6,5,4"

creo que MySQL está haciendo algún tipo de unión de los differents filas devueltas por la consulta y luego concatenando todo.

Mi resultado esperado es (para el último ejemplo):

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

puedo obtener esa utilizando DISTINCT en GROUP_CONCAT, pero luego tengo otro problema: Si tengo dos imágenes con el mismo título, una de ellas es omitida, y luego aparece algo así como:
images_id = "7,3,5"
images_title = "Título 7 y 3, título 5"

Así que echo de menos la relación entre images_id y images_title.

¿Alguien sabe si es posible realizar esta consulta en MySQL?

Tal vez estoy complicando todo sin ningún beneficio real. Estoy tratando de ejecutar solo una consulta por el rendimiento, pero ahora no estoy tan seguro de si es aún más rápido ejecutar dos consultas (una para seleccionar las facetas y otra para las imágenes, por ejemplo).

Explique cuál cree que es la mejor solución para esto y por qué.

Gracias!

Respuesta

8

Tendrá que obtener cada grupo por separado:

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

No entiendo muy bien su consulta, pero parece muy compleja, quiero decir, necesitamos una subselección con un grupo por cada concat? Parece algo muy lento, ¿no es más rápido 2 consultas? – Enrique

+2

@Enrique, no se trata de velocidad, se trata de corrección. Si mi código no necesita funcionar realmente, puedo hacer todo al instante. – Johan

+0

@Enrique, No necesita una sub-selección para cada grupo concat, solo para aquellas tablas donde el partido contra p.id devuelve más de 1 fila por p.id. – Johan

1

Si el problema es la velocidad, entonces puede ser mucho más rápido que sólo tiene que seleccionar todos los datos que necesita como filas separadas, y hacer la agrupación en la aplicación, es decir:

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

Luego, en la aplicación:

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

Sólo añadir DISTINCT.

Ejemplo:
GROUP_CONCAT(DISTINCT image.id) AS images_id

+0

+1, también es trabajo para SQLite3 – user457015

+0

Creo que esto debe ampliarse. ''DISTINCT' => GROUP_CONCAT (DISTINCT image.id) AS images_id' no parece ser sintaxis SQL, y MySQL 5.1 arroja un error de sintaxis. El interrogador no mencionó ningún lenguaje de programación, por lo que si esta respuesta no es SQL, debe convertirse o explicarse. – Animism

+0

Múltiples 'GROUP_CONCAT's sin filas adicionales. +1 –

4

Puede añadir la palabra clave DISTINCT, obtendrá los resultados deseados.

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 
Cuestiones relacionadas