2010-06-21 15 views
122

Estoy haciendo SELECT GROUP_CONCAT(categories SEPARATOR ' ') FROM table. datos de la muestra a continuación:MySQL DISTINCT en un GROUP_CONCAT()

categories 
---------- 
test1 test2 test3 
test4 
test1 test3 
test1 test3 

Sin embargo, yo estoy recibiendo test1 test2 test3 test4 test1 test3 atrás y me gustaría obtener test1 test2 test3 test4 espalda. ¿Algunas ideas?

¡Muchas gracias!

Respuesta

259

GROUP_CONCAT tiene atributos distintos:

SELECT GROUP_CONCAT(DISTINCT categories ORDER BY categories ASC SEPARATOR ' ') FROM table 
34

Usando DISTINCT trabajará

SELECT GROUP_CONCAT(DISTINCT(categories) SEPARATOR ' ') FROM table 

ref: - this

16

Otras respuestas a esta pregunta no devuelve lo que necesita el OP, lo harán devolver una cadena como:

test1 test2 test3 test1 test3 test4 

(observe que test1 y test3 están duplicados), mientras que el PO quiere volver esta cadena:

test1 test2 test3 test4 

el problema aquí es que la cadena "test1 test3" se duplica y se inserta una sola vez, pero todos los demás son distinto entre sí ("test1 test2 test3" es distinto de "test1 test3", incluso si algunas pruebas contenidas en toda la cadena están duplicadas).

Lo que tenemos que hacer aquí es dividir cada cadena en diferentes filas, y en primer lugar hay que crear una tabla de números:

CREATE TABLE numbers (n INT); 
INSERT INTO numbers VALUES 
(1),(2),(3),(4),(5),(6),(7),(8),(9),(10); 

entonces podemos ejecutar esta consulta:

SELECT 
    SUBSTRING_INDEX(
    SUBSTRING_INDEX(tableName.categories, ' ', numbers.n), 
    ' ', 
    -1) category 
FROM 
    numbers INNER JOIN tableName 
    ON 
    LENGTH(tableName.categories)>= 
    LENGTH(REPLACE(tableName.categories, ' ', ''))+numbers.n-1; 

y obtenemos un resultado como este:

test1 
test4 
test1 
test1 
test2 
test3 
test3 
test3 

y luego podemos aplicar la función de agregado GROUP_CONCAT, nosotros ing cláusula DISTINCT:

SELECT 
    GROUP_CONCAT(DISTINCT category ORDER BY category SEPARATOR ' ') 
FROM (
    SELECT 
    SUBSTRING_INDEX(SUBSTRING_INDEX(tableName.categories, ' ', numbers.n), ' ', -1) category 
    FROM 
    numbers INNER JOIN tableName 
    ON LENGTH(tableName.categories)>=LENGTH(REPLACE(tableName.categories, ' ', ''))+numbers.n-1 
) s; 

favor ver violín here.

+0

Parece que su interpretación de la pregunta de OP puede ser correcta; sin embargo, creo que debería señalarse que la normalización de los datos mediante la creación de una tabla "blah_to_categories" y una tabla de "categorías" para la relación adecuada de muchos a muchos sería la mejor práctica aquí, y agregaría mucha flexibilidad. Aún así, su respuesta es una solución inteligente para cualquiera que herede un esquema tan desnormalizado. También podría probablemente adaptarse con el propósito de generar una migración del esquema antiguo al normalizado. – XP84

6
SELECT 
    GROUP_CONCAT(DISTINCT (category)) 
FROM (
    SELECT 
    SUBSTRING_INDEX(SUBSTRING_INDEX(tableName.categories, ' ', numbers.n), ' ', -1) category 
    FROM 
    numbers INNER JOIN tableName 
    ON LENGTH(tableName.categories)>=LENGTH(REPLACE(tableName.categories, ' ', ''))+numbers.n-1 
) s; 

Esto devolverá valores distintos como: test1, test2, test4, test3

1

realizo esta pregunta es viejo, pero siento que esto debe ser mencionado: GROUP_CONCAT con distinta = asesino rendimiento. Si trabajas en bases de datos pequeñas, no lo notarás, pero cuando se escala, no funcionará muy bien.

+1

Estoy trabajando con una tabla de 10 millones de filas y mi consulta toma el mismo tiempo con o sin DISTINCT. Estoy usando InnoDB. – ashishduh

+0

¿Qué tipo de datos? ¿Cuántas columnas? En mi base de datos, es pesado en los campos de texto grandes y hay alrededor de 30 algunas columnas impares usando distintas. Quitar distintas velocidades lo acelera dramáticamente, y está usando Innodb. – photocode