Thread View: pl.comp.bazy-danych
8 messages
8 total messages
Started by Marek
Fri, 06 Feb 2015 10:32
PostgreSQL - dziwny błąd składni zapytania
Author: Marek
Date: Fri, 06 Feb 2015 10:32
Date: Fri, 06 Feb 2015 10:32
32 lines
1697 bytes
1697 bytes
Witam, W poniższym zapytaniu nie działa JOIN: WITH RECURSIVE is_child(group_id) AS ( SELECT group_id FROM user_control WHERE user_control_id=21 UNION ALL SELECT ic.group_id FROM is_child ic JOIN user_control uc ON (uc.user_control_id=ic.group.id) ) SELECT group_id FROM is_child; Ponoć nie istnieje schemat ic. Gdy usunę linię z JOINem, zapytanie wykonuje się, czyli ic istnieje. O co może chodzić? No i kolejna rzecz, której nie rozumiem. Jeśli zmodyfikuję drugą linię dodając ORDER BY: WITH RECURSIVE is_child(group_id) AS ( SELECT group_id FROM user_control WHERE user_control_id=21 ORDER BY cośtam to powstaje jakiś konflikt z UNION ALL (błąd składni). Gdy zmienię to na: WITH RECURSIVE is_child(group_id) AS ( SELECT * FROM (SELECT group_id FROM user_control WHERE user_control_id=21 ORDER BY cośtam) AS foo działa... Co jest grane? -- Pozdrawiam, Marek
Re: PostgreSQL - dziwny błąd składni zapytania
Author: Marek
Date: Fri, 06 Feb 2015 13:39
Date: Fri, 06 Feb 2015 13:39
25 lines
1611 bytes
1611 bytes
W dniu 2015-02-06 o 11:32, Marek pisze: > Witam, > > W poniższym zapytaniu nie działa JOIN: > > WITH RECURSIVE is_child(group_id) AS ( > SELECT group_id FROM user_control WHERE user_control_id=21 > UNION ALL > SELECT ic.group_id FROM is_child ic > JOIN user_control uc ON (uc.user_control_id=ic.group.id) > ) > SELECT group_id FROM is_child; > > Ponoć nie istnieje schemat ic. Gdy usunę linię z JOINem, zapytanie > wykonuje się, czyli ic istnieje. O co może chodzić? Tą część pytania anuluję. Dopiero teraz dostrzegłem, że mam kropkę w group.id zamiast group_id :-D Jednakże nadal nie rozumiem czemu w UNION ALL nie można stosować w składowych zapytaniach sekcji ORDER BY. -- Pozdrawiam, Marek
Re: PostgreSQL - dziwny błąd składni zapytania
Author: irq
Date: Fri, 06 Feb 2015 15:28
Date: Fri, 06 Feb 2015 15:28
19 lines
2811 bytes
2811 bytes
W dniu piątek, 6 lutego 2015 14:40:00 UTC+1 użytkownik Marek napisał: > > Jednakże nadal nie rozumiem czemu w UNION ALL nie można stosować w > składowych zapytaniach sekcji ORDER BY. > > -- > Pozdrawiam, > Marek ... bo UNION nie gwarantuje zachowania kolejności wierszy poszczególnych składników, tak jak, co do zasady, relacyjna baza danych jest zwolniona z dbania o jakikolwiek porządek elementów przechowywanych obiektów. ORDER BY służy jedynie to finalnego porządkowania wyników całego zapytania. Ma to odzwierciedlenie w syntaksie: http://www.postgresql.org/docs/9.4/static/sql-select.html, gdzie [ORDER BY ... ] występuje po [ ... UNION ... ]. Tak więc jeżeli nawet opakujesz składnik unii w podzapytanie i wymusisz jego posortowanie, tak jak pokazałeś jako przypadek "działający", to i tak efekt tego sortowania zostanie zniszczony przez UNION (a przynajmniej nie ma gwarancji jego niezniszczenia). Z powyższego wynika również, że i ORDER BY zastosowany poprawnie za całą unią, ale nadal w obrębie CTE, nadal nie na wiele się przyda, bo analogicznie, nie ma gwarancji co do tego w jakim porządku zostanie zwrócony wynik tego CTE przez zewnętrzny SELECT group_id FROM is_child. Dlatego, jeżeli już musisz tu cokolwiek posortować i nie ma w tym dodatkowego ukrytego zamiaru, potrzebujesz napisać: WITH ... is_child ... AS (...) SELECT group_id FROM is_child ORDER BY 1.
Re: PostgreSQL - dziwny błąd składni zapytania
Author: Marek
Date: Fri, 06 Feb 2015 18:00
Date: Fri, 06 Feb 2015 18:00
75 lines
3219 bytes
3219 bytes
W dniu 2015-02-06 o 16:28, irq pisze:
> ... bo UNION nie gwarantuje zachowania kolejności wierszy
> poszczególnych składników,
Ahhhh... faktycznie! Masz rację.
Ale... coś mi tu nie pasuje gdyż to implikuje bezcelowość istnienia
zapytania rekurencyjnego WITH RECURSIVE...
Np mamy drzewo kategorii:
CREATE TABLE category (
category_id SERIAL PRIMARY KEY,
parent_id int4 REFERENCES category (category_id)
order_idx int4
...
parent_id to ID rodzica lub null
order_idx oznacza kolejność danej kategorii w gałązce
Chcemy je przerzucić do XMLa więc musimy je przetrawersować
uwzględniając hierarchię. Zapytanie rekurencyjne, które (chyba) do tego
służy, powinno przejść przez tą strukturę rekurencyjnie i zachować
kolejność. a jeśli UNION ALL, które musi być składnikiem tej rekurencji
(bo taka jest składnia) nie gwarantuje kolejności, to cała zabawa traci
sens. Czy też dostrzegasz sprzeczność?
Konkretnie w tym przypadku zrobiłbym tak (co hipotetycznie nie może
zadziałać poprawnie choć działa):
WITH RECURSIVE hierarchy(category_id) AS (
SELECT * FROM --obejście dla niemożności stosowania order by
(SELECT category_id FROM category WHERE parent_idx ISNULL ORDER BY
order_idx) AS table1 -- wybiera w/g kolejności kategorie nadrzędne
UNION ALL
SELECT * FROM --kolejne obejście dla braku sortowania
(SELECT * FROM hierarchy h
JOIN category c ON (c.parent_id=h.category_id)
ORDER BY c.order_idx) AS table2
)
SELECT * FROM hierarchy;
No i zapytanie zwraca mi pięknie posortowane drzewko. Przykładowo gdy
mam rekordy:
category_id | parent_id | nazwa
--------------------------------
1 null k1
2 null k2
3 1 k1.1
4 1 k1.2
5 2 k2.1
6 4 k1.2.1
Daje kolejność:
k1
k1.1
k1.2
k1.2.1
k2
k2.1
Jeśli struktura RECURSIVE WITH nie umiałaby sortować w specyficzny
sposób, to dawałaby taki sam rezultat jak SELECT * FROM category. To jak
to jest z tym UNION ALL, że mimo to nie powoduje iż RECURSIVE WITH
funkcjonuje?
--
Pozdrawiam,
Marek
Re: PostgreSQL - dziwny błąd składni zapytania
Author: Marek
Date: Fri, 06 Feb 2015 18:48
Date: Fri, 06 Feb 2015 18:48
16 lines
1224 bytes
1224 bytes
To jak > to jest z tym UNION ALL, że mimo to nie powoduje iż RECURSIVE WITH > funkcjonuje? Miało być: To jak to jest z tym UNION ALL, że mimo to powoduje iż RECURSIVE WITH funkcjonuje? -- Pozdrawiam, Marek
Re: PostgreSQL - dziwny błąd składni zapytania
Author: irq
Date: Mon, 09 Feb 2015 15:32
Date: Mon, 09 Feb 2015 15:32
30 lines
3254 bytes
3254 bytes
W dniu piątek, 6 lutego 2015 19:00:40 UTC+1 użytkownik Marek napisał: > Konkretnie w tym przypadku zrobiłbym tak (co hipotetycznie nie może > zadziałać poprawnie choć działa): > > WITH RECURSIVE hierarchy(category_id) AS ( > > SELECT * FROM --obejście dla niemożności stosowania order by > (SELECT category_id FROM category WHERE parent_idx ISNULL ORDER BY > order_idx) AS table1 -- wybiera w/g kolejności kategorie nadrzędne > > UNION ALL > > SELECT * FROM --kolejne obejście dla braku sortowania > (SELECT * FROM hierarchy h > JOIN category c ON (c.parent_id=h.category_id) > ORDER BY c.order_idx) AS table2 > > ) > SELECT * FROM hierarchy; > > No i zapytanie zwraca mi pięknie posortowane drzewko. podobnie jak pisałem wcześniej, to posortowanie może być zbieżne z oczekiwanym tylko przez przypadek, w związku z konkretnym planem wykonania i jego implementacją. Ta może się zmieniać z wersji na wersję, z silnika na silnik - jeżeli rozważać nie tylko PostgreSQL. Plan wykonania może być zależny od złożoności danych, objętości danych, dostępnych indeksów, itd. Wymagane i oczekiwane przez Ciebie sortowanie, możesz zagwarantować jedynie poprzez dodanie odpowiedniego ORDER BY po zewnętrznym SELECT * FROM hierarchy. Przeczytaj pierwszy akapit tutaj: http://www.postgresql.org/docs/9.4/static/queries-order.html. Zwróć uwagę na drugie zdanie. Mówi ono, że swoimi ORDER BY wewnątrz WITH RECURSIVE może Ci się udać wymusić jakiś efekt, ale tylko doraźnie, bez gwarantowanej powtarzalności. Ostatnie zdanie mówi co trzeba zrobić aby rzeczywiście posortować ostateczny resultset w sposób stały i przewidywalny. Szkoda że nie zamieściłeś kompletnego spójnego przykładu. Fragmenty, które wkleiłeś nie trzymają się kupy, a szkoda, bo można by potestować. Co będzie gdy odwrócisz kierunek sortowania w podzapytaniach?
Re: PostgreSQL - dziwny błąd składni zapytania
Author: Marek
Date: Mon, 09 Feb 2015 22:56
Date: Mon, 09 Feb 2015 22:56
48 lines
2698 bytes
2698 bytes
W dniu 2015-02-09 o 16:32, irq pisze: > Szkoda że nie zamieściłeś kompletnego spójnego przykładu. Fragmenty, > które wkleiłeś nie trzymają się kupy, a szkoda, bo można by > potestować. Ok, zamieszczam, choć uproszę go. Wywalę zbyteczne pola. > Co będzie gdy odwrócisz kierunek sortowania w > podzapytaniach? Katastrofa. WITH RECURSIVE get_tree(user_control_id, group_id, weight) AS ( SELECT * FROM (SELECT uc.user_control_id, uc.group_id, weight FROM user_control uc WHERE group_id ISNULL ORDER BY weight) AS table1 UNION ALL SELECT * FROM (SELECT uc.user_control_id, uc.group_id, weight FROM get_tree gt JOIN user_control uc ON (uc.group_id=gt.user_control_id) ORDER BY weight) AS table2 ) SELECT * FROM get_tree Wyjaśniam o co chodzi. Tabela user_control to drzewo hierarchiczne obiektów. Pole group_id wskazuje na rodzica lub jest null'em gdy obiekt jest nadrzędny. Tak więc w pierwszym podzapytaniu zwracam wszystkie obiekty nadrzędne posortowane wagą a potem zbieram podobiekty przypisane do nich a potem przypisane do przypisanych itd. Kolumna weight określa ich porządek w gałęzi. Zawsze weight zaczyna się od 1, potem 2 itd. Gdy w drugim podzapytaniu usuwam ORDER BY - wynik jest żaden. Otrzymuję NULL - nie wiem czemu. Chcę otrzymać wynik w postaci posortowanych wagą obiektów nadrzędnych, potem posortowanych wagą przypisanych obiektów przypisanych itd. Nie wyobrażam sobie sortowania w SELECT * FROM get_tree, które uporządkuje rekordy jak oczekuję. -- Pozdrawiam, Marek
Re: PostgreSQL - dziwny błąd składni zapytania
Author: irq
Date: Tue, 10 Feb 2015 07:43
Date: Tue, 10 Feb 2015 07:43
10 lines
1882 bytes
1882 bytes
W dniu poniedziałek, 9 lutego 2015 23:56:49 UTC+1 użytkownik Marek napisał: > W dniu 2015-02-09 o 16:32, irq pisze: > > > Szkoda że nie zamieściłeś kompletnego spójnego przykładu. Fragmenty, > > które wkleiłeś nie trzymają się kupy, a szkoda, bo można by > > potestować. > > Ok, zamieszczam Ok, ale jak mam uruchomić tę kwerendę? Czy mógłbyś dodać też CREATE TABLE i INSERT przykładowych danych?
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads