MySQL DISTINCT na GROUP_CONCAT ()

185

Robie SELECT GROUP_CONCAT(categories SEPARATOR ' ') FROM table. Przykładowe dane poniżej:

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

Jednak test1 test2 test3 test4 test1 test3wracam i chciałbym test1 test2 test3 test4wrócić. Jakieś pomysły?

Wielkie dzięki!

użytkownik371990
źródło

Odpowiedzi:

363

GROUP_CONCAT ma atrybut DISTINCT:

SELECT GROUP_CONCAT(DISTINCT categories ORDER BY categories ASC SEPARATOR ' ') FROM table
Naktibalda
źródło
48

Korzystanie z DISTINCT będzie działać

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

ODNIESIENIE: - to

Salil
źródło
19

DISTINCT: daje unikalne wartości.

SELECT GROUP_CONCAT(DISTINCT(categories )) AS categories FROM table
Goshika Mahesh
źródło
17

Inne odpowiedzi na to pytanie nie zwracają tego, czego potrzebuje OP, zwracają ciąg znaków:

test1 test2 test3 test1 test3 test4

(zauważ, że test1i test3są powielone), podczas gdy OP chce zwrócić ten ciąg:

test1 test2 test3 test4

Problem polega na tym, że ciąg "test1 test3"jest duplikowany i wstawiany tylko raz, ale wszystkie pozostałe są od siebie różne ( "test1 test2 test3"różni się "test1 test3", nawet jeśli niektóre testy zawarte w całym ciągu są powielone).

Musimy tutaj podzielić każdy ciąg na różne wiersze, a najpierw musimy utworzyć tabelę liczb:

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

możemy uruchomić to zapytanie:

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;

i otrzymujemy taki wynik:

test1
test4
test1
test1
test2
test3
test3
test3

a następnie możemy zastosować funkcję agregującą GROUP_CONCAT, używając klauzuli 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;

Zobacz skrzypce tutaj .

fthiella
źródło
Wygląda na to, że Twoja interpretacja pytania OP może być słuszna; Myślę jednak, że należy zauważyć, że normalizacja danych poprzez utworzenie tabeli „blah_to_categories” i tabeli „kategorii” dla odpowiedniej relacji wiele do wielu byłaby tutaj najlepszą praktyką i zapewniłaby dużą elastyczność. Mimo to twoja odpowiedź stanowi sprytne obejście dla każdego, kto odziedziczy taki zdenormalizowany schemat. Prawdopodobnie można go również dostosować w celu wygenerowania migracji ze starego do znormalizowanego schematu.
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;   

Zwróci to różne wartości, takie jak: test1, test2, test4, test3

Sainath
źródło
5

Możesz po prostu dodać DISTINCT z przodu.

SELECT GROUP_CONCAT(DISTINCT categories SEPARATOR ' ')

jeśli chcesz sortować,

SELECT GROUP_CONCAT(DISTINCT categories ORDER BY categories ASC SEPARATOR ' ')
Mohideen bin Mohammed
źródło