EpicWEB.pl

webdesign, programowanie, phat lewt!

Ostatni projekt

ddrpl.com

Ostatnie wiadomości

Funkcja GROUP_CONCAT()

Zapewne wielu z was (nas) miało nie raz styczność z poniższym zagadnieniem:

System aktualności z podziałem na kategorie, z założeniem, że jedna aktualność może należeć do wielu kategorii - np. system blogowy. Zakładając, że wiemy co to normalizacja bazy danych, robimy coś mniej więcej takiego:

  1. tabela `posts` (id, title, text)
  2. tabela `tags` (id, name)
  3. tabela `tags_to_posts` (post_id, tag_id)

Następnie, w celu wybrania postów i kategorii doń należących wywołujemy minimum 2 zaptytania:

Wybieramy wiadomości (zapytanie A):

SELECT * FROM `posts`

I w pętli wybieramy kategorie (zapytanie B):

SELECT t.name FROM `tags_to_posts` LEFT JOIN `tags` ON tags.id = tags_to_posts.tag_id WHERE tags_to_posts.post_id = ID_POSTU

Niby nic złego, i wiele osób zasugeruje takie właśnie rozwiązanie. Istnieje natomiast prostsze rozwiązanie, pozwalające nam wyciągnąć wszystkie interesujące nas informacje za jednym razem - jedyny warunek - MySQL >= 4.1

Powitajmy GROUP_CONCAT()

GROUP_CONCAT(nazwa_pola ORDER BY nazwa_pola SEPARATOR ',')

Przykład zastosowania (zapytanie C):

SELECT p.*, GROUP_CONCAT(t.name ORDER BY t.name SEPARATOR ', ' ) AS `kategorie` FROM `posts` AS `p` LEFT JOIN `tags_to_posts` AS `ttp` ON ttp.post_id = p.id LEFT JOIN `tags` AS `t` ON t.id = ttp.tag_id GROUP BY p.id

W wyniku zapytania otrzymamy wszystkie dane z tabeli `posts` ORAZ nową kolumnę o nazwie kategorie zawierającą wszystkie kategorie do których należy dany post oddzielone przecinkiem.

Co prawda zamiast dwóch prostych SELECTów zastosowaliśmy dwa LEFT JOINy - ale jeżeli przyjrzymy się bliżej, okazuje się, że zaoszczędziliśmy N zapytań, gdzie N to ilość pobranych przez zapytanie A aktualności (zapytanie B wykonywane jest w pętli dla każdego rekordu pobranego w zapytaniu A).

Więcej informacji (oraz przykładów zastosowania) znajdziesz w manualu MySQL.

Zostaw komentarz