MySQL DISTINCT em um GROUP_CONCAT ()

186

Eu estou fazendo SELECT GROUP_CONCAT(categories SEPARATOR ' ') FROM table. Dados de exemplo abaixo:

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

No entanto, estou test1 test2 test3 test4 test1 test3voltando e gostaria de recebertest1 test2 test3 test4 voltar. Alguma ideia?

Muito Obrigado!

user371990
fonte

Respostas:

364

GROUP_CONCAT possui o atributo DISTINCT:

SELECT GROUP_CONCAT(DISTINCT categories ORDER BY categories ASC SEPARATOR ' ') FROM table
Naktibalda
fonte
48

O uso do DISTINCT funcionará

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

REf: - isto

Salil
fonte
20

DISTINCT: will fornece valores únicos.

SELECT GROUP_CONCAT(DISTINCT(categories )) AS categories FROM table
Goshika Mahesh
fonte
17

Outras respostas a esta pergunta não retornam o que o OP precisa, elas retornarão uma string como:

test1 test2 test3 test1 test3 test4

(observe que test1e test3são duplicados) enquanto o OP deseja retornar essa sequência:

test1 test2 test3 test4

o problema aqui é que a cadeia de caracteres "test1 test3"é duplicada e inserida apenas uma vez, mas todas as outras são distintas uma da outra ( "test1 test2 test3"é diferente de"test1 test3" , mesmo que alguns testes contidos na cadeia inteira sejam duplicados).

O que precisamos fazer aqui é dividir cada sequência em linhas diferentes, e primeiro precisamos criar uma tabela de números:

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

então podemos executar 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;

e obtemos um resultado como este:

test1
test4
test1
test1
test2
test3
test3
test3

e então podemos aplicar a função agregada GROUP_CONCAT, usando a 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;

Por favor, veja violino aqui .

fthiella
fonte
Parece que sua interpretação da pergunta do OP pode estar certa; no entanto, acho que deve ser salientado que normalizar os dados criando uma tabela "blah_to_categories" e "categorias" para o relacionamento muitos-para-muitos apropriado seria a melhor prática aqui e acrescentaria muita flexibilidade. Ainda assim, sua resposta é uma solução alternativa inteligente para quem herda um esquema tão desnormalizado. Provavelmente também poderia ser adaptado com o objetivo de gerar uma migração do esquema antigo para o esquema normalizado.
XP84 01/06
11
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;   

Isso retornará valores distintos como: test1, test2, test4, test3

Sainath
fonte
6

Você pode simplesmente adicionar DISTINCT na frente.

SELECT GROUP_CONCAT(DISTINCT categories SEPARATOR ' ')

se você quiser classificar,

SELECT GROUP_CONCAT(DISTINCT categories ORDER BY categories ASC SEPARATOR ' ')
Mohideen bin Mohammed
fonte