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
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
nie znam mysql’a, ale czym on łączy stringi przy group_concat? czy da się to prosto zmienić?
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
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 …
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?
nie pozwolić na dodanie. dlatego prawdziwa replikacja multimaster działa tylko gdy jest synchroniczna.
niestety tego typu rozwiązania są kosztowne. mocno.
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
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.
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ć.