MySQL DISTINCT для GROUP_CONCAT ()

186

Я делаю SELECT GROUP_CONCAT(categories SEPARATOR ' ') FROM table. Пример данных ниже:

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

Тем не менее, я test1 test2 test3 test4 test1 test3возвращаюсь, и я хотел бы test1 test2 test3 test4вернуться. Любые идеи?

Большое спасибо!

user371990
источник

Ответы:

364

GROUP_CONCAT имеет атрибут DISTINCT:

SELECT GROUP_CONCAT(DISTINCT categories ORDER BY categories ASC SEPARATOR ' ') FROM table
Naktibalda
источник
48

Использование DISTINCT будет работать

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

REf: - это

Salil
источник
20

DISTINCT: даст вам уникальные значения.

SELECT GROUP_CONCAT(DISTINCT(categories )) AS categories FROM table
Гошика Махеш
источник
17

Другие ответы на этот вопрос не возвращают то, что нужно OP, они возвращают строку вроде:

test1 test2 test3 test1 test3 test4

(обратите внимание, что test1и test3дублируются), в то время как OP хочет вернуть эту строку:

test1 test2 test3 test4

проблема здесь в том, что строка "test1 test3"дублируется и вставляется только один раз, но все остальные отличаются друг от друга ( "test1 test2 test3"чем отличается "test1 test3", даже если некоторые тесты, содержащиеся во всей строке, дублируются).

Здесь нам нужно разбить каждую строку на разные строки, и сначала нам нужно создать таблицу чисел:

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

тогда мы можем выполнить этот запрос:

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;

и мы получаем такой результат:

test1
test4
test1
test1
test2
test3
test3
test3

и тогда мы можем применить агрегатную функцию GROUP_CONCAT, используя предложение 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;

Пожалуйста, смотрите скрипку здесь .

fthiella
источник
Похоже, что ваша интерпретация вопроса ОП может быть правильной; однако, я думаю, следует отметить, что нормализация данных путем создания таблицы «blah_to_categories» и «категорий» для соответствующего отношения «многие ко многим» была бы наилучшей практикой и добавила бы большую гибкость. Тем не менее, ваш ответ - разумный обходной путь для всех, кто наследует такую ​​денормализованную схему. Возможно, его также можно адаптировать для генерации перехода от старой к нормализованной схеме.
XP84
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;   

Это возвратит различные значения как: test1, test2, test4, test3

Sainath
источник
6

Вы можете просто добавить DISTINCT впереди.

SELECT GROUP_CONCAT(DISTINCT categories SEPARATOR ' ')

если вы хотите отсортировать,

SELECT GROUP_CONCAT(DISTINCT categories ORDER BY categories ASC SEPARATOR ' ')
Мохидин бин Мухаммед
источник