May 20th, 2006 by depesz | Tags: | 9 comments »
Did it help? If yes - maybe you can help me?

czasem jest taka potrzeba by zwrócić kilka połączonych stringów z kolejnych rekordów.

np.:

mając tabelkę z takimi danymi:

> select pracownik from pracownicy where firma_id = 1;

  • Jan Kowalski
  • Hubert Lubaczewski
  • Piotr Nowak
  • Adam Słodowy

chcielibyśmy dostać jedno pole z zawartością:

Jan Kowalski, Hubert Lubaczewski, Piotr Nowak, Adam Słodowy

lub wręcz posortowane:

Adam Słodowy, Hubert Lubaczewski, Jan Kowalski, Piotr Nowak

aby to zrobić najwygodniej jest zdefiniować własny agregat (czyli funkcję taką jak min(), max(), sum(), avg()).

najpierw zdefiniujemy funkcję łączącą:

CREATE OR replace function agg_text_sum(txt_before TEXT, txt_new TEXT) RETURNS TEXT AS
$BODY$
DECLARE
BEGIN
IF (txt_before IS NULL) THEN
RETURN txt_new;
END IF;
RETURN txt_before || ‘, ‘ || txt_new;
END;
$BODY$
LANGUAGE ‘plpgsql';

następnie tworzymy agregat:

CREATE aggregate text_sum (
basetype = TEXT,
sfunc = agg_text_sum,
stype = TEXT
);

i już możemy:

> select text_sum(pracownik) from pracownicy where firma_id = 1;

  • Jan Kowalski, Hubert Lubaczewski, Piotr Nowak, Adam Słodowy

aby to posortować trzeba uciec się do podzapytań:

> select text_sum(pracownik) from (select pracownik from pracownicy where firma_id = 1 order by pracownik) x;

  • Adam Słodowy, Hubert Lubaczewski, Jan Kowalski, Piotr Nowak
  1. 9 comments

  2. # premax
    May 20, 2006

    A gdybyś miał MySQL to napisałbyś:
    select group_concat(pracownik) from pracownicy
    where firma_id=1

    Bez tworzenia żadnych funkcji :> A, chciałeś posortowane. Nic prostszego, również można sobie odpuścić podzapytania :>
    select group_concat(pracownik order by pracownik) from pracownicy
    where firma_id=1

    Więcej: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html

  3. May 20, 2006

    nie znam mysql’a, ale czym on łączy stringi przy group_concat? czy da się to prosto zmienić?

  4. # premax
    May 20, 2006

    Naturalnie, że da się zmienić. Domyślnie łączy przecinkiem.
    A teraz połączy blah’em 😉

    select group_concat(pracownik SEPARATOR ‘blah’) from pracownicy
    where firma_id=1

  5. May 20, 2006

    fajne.
    mysql ma sporo naprawde sympatycznych rzeczy.
    choc z drugiej strony – widze tam wiele dziwnego entuzjazmu. np. jakos ostatnio czytalem o tym, ze na 5.x da sie zrobic replikacje multi-master z automatycznym fileoverem. ale sa “ale”:
    1. aby to zadzialalo trzeba uzywac 5.1.x ktore jest developerskie
    2. multi-master owszem jest. dopoki sie nie uzywa kluczy unikalnych (takich jak np. username).

    nie zmienia to jednak faktu, ze mysql sie zmienia w dobrym kierunku i jest coraz bardziej sympatyczna baza. ale ja juz chyba za stary jestem by sie go uczyc …

  6. # premax
    May 20, 2006

    Jeśli chodzi o multi-master replikację, to chyba nic się nie zmieniło między stabilną 5.0 i betą 5.1, poza tym, że oczywiście w 5.1 dodano replikację row-based oprócz od dawna istniejącej statement-based.

    Co do unikalnych kluczy na wielu masterach — jak sobie wyobrażasz, że to miałoby działać? Co ma zrobić slave gdy napotka rekord z unikalnym kluczem, który już pobrał od innego mastera?

  7. May 20, 2006

    nie pozwolić na dodanie. dlatego prawdziwa replikacja multimaster działa tylko gdy jest synchroniczna.
    niestety tego typu rozwiązania są kosztowne. mocno.

  8. # premax
    May 20, 2006

    W MySQL mozesz osiągnąć więc to samo: w przypadku gdy zreplikowane dane powodują błąd, można nakazać go slave’owi zignorować i nasłuchiwać dalej.
    –slave-skip-errors=[err_code1,err_code2,…|all]
    np. 1062 duplicate entry

  9. May 20, 2006

    ok, ale te bledne dane pozostaja.
    przynajmniej tak to rozumiem.
    tzn. mam tabele users (id, username (unique), haslo);
    na jednym nodzie dodaje username=depesz, haslo = ‘blabluga’;
    na drugim dodaje username=depesz, haslo = dasdsa
    i jak rozumiem bazy sie roznia.

    ale to akurat najmniejsza kwestia. do mojego ulubionego postgresa tez nie ma replikacji multi-master (ani nawet master multi-slave synchronicznej). moze za jakis czas bedzie. na razie trzeba sobie dawac rade pgpoolem lub (jak kogos stac) pclustrem czy bizgresmpp’em.

  10. # premax
    May 20, 2006

    Ano pozostają. Nie ma z tym zwykle problemu, bo się decyduje ręcznie jakie dane na których masterach wrzucąć. Problem był z kluczami podstawowymi autoinkrementowanymi, ale w MySQL jest sposób, żeby to obejść (różna inkrementacja na masterach). W Postgres zresztą analogicznie — tylko inne sekwencje trzeba zrobić.

Sorry, comments for this post are disabled.