2010-06-21 3 views
122

Я делаю SELECT GROUP_CONCAT(categories SEPARATOR ' ') FROM table. Выборочные данные ниже:MySQL DISTINCT на GROUP_CONCAT()

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

Однако я получаю test1 test2 test3 test4 test1 test3 назад, и я хотел бы получить test1 test2 test3 test4 обратно. Есть идеи?

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

ответ

259

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

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

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

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

ЛОТ: - this

16

Другие ответы на этот вопрос не возвращают то, что потребности О.П., они будут верните строку как:

test1 test2 test3 test1 test3 test4 

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

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, нас ING 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; 

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

+0

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

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

1

Я понимаю, что этот вопрос старый, но я чувствую, как это должно быть указано: GROUP_CONCAT с отчетливым = производительность киллера. Если вы работаете в небольших базах данных, вы не заметите, но когда он масштабируется - он не будет работать очень хорошо.

+1

Я работаю с таблицей из 10 миллионов строк, и мой запрос занимает одно и то же время с DISTINCT или без него. Я использую InnoDB. – ashishduh

+0

Какой тип данных? Сколько столбцов? В моей БД, он тяжелый в больших текстовых полях, и есть около 30 некоторых нечетных столбцов, использующих разные. Убирать отдельно, ускоряет его, и он использует Innodb. – photocode

Смежные вопросы