2014-11-26 15 views
5

Mam tabelę z kolumną ścieżki w systemie. W mojej hierarchii ścieżka do etykiety jest unikalna, co oznacza, że ​​każda etykieta ma dokładnie jedną etykietę nadrzędną. Innymi słowy, w tabeli nie ma dwóch ścieżek, które kończyłyby się tą samą etykietą.PostgreSQL ltree znajdź wszystkich przodków danej etykiety (bez ścieżki)

Mam etykietkę "ltree", powiedzmy "C".

mogę znaleźć wszystkie wiersze tego potomka etykieta z następującym zapytaniem:

select * from myTree where path ~ '*.C.*'; 

To działa prawidłowo i daje poprawne poddrzewa.

Teraz muszę zaimplementować zapytanie, aby znaleźć wszystkie wiersze nadrzędne tej etykiety. Chodzi mi o to, że jeśli w tabeli znajdują się na przykład 3 wiersze z etykietami "A", "AB", "ABC", chciałbym uzyskać wiersze ze ścieżkami "A" i "AB" (prawdopodobnie włącznie z "ABC", na razie nie ma znaczenia).

Jeśli znam pełną ścieżkę "C" ("A.B.C" w powyższym przykładzie), zadanie jest proste z operatorem @>. Jednak teraz wiem tylko "C" i nadal chciałbym osiągnąć to zadanie za pomocą pojedynczego zapytania. Czy jest jakiś sposób to zrobić?

+0

Nie znalazłem żadnego bezpośredniego wsparcia dla tego w 'ltree', ale możesz wybrać węzeł podrzędny z' path ~ '* .C'', a następnie możesz wykonać samołączenie, aby uzyskać wszystkie przodkowie. – pozs

+0

Dzięki, też spróbuję. –

+0

Skąd znasz "C", ale nie pełną ścieżkę "A.B.C"? Czy nie są w tym samym rzędzie stołu? –

Odpowiedz

12
SELECT 
    * 
FROM 
    myTree 
WHERE 
    path @> (
    SELECT 
     path 
    FROM 
     myTree 
    WHERE 
     label = 'C' 
); 
+0

Jezus, który był dość prosty. To zbyt dużo godzin teraz, kiedy siedzę przy komputerze :) Do czasu, gdy udało mi się go zaimplementować z samołączeniem, ale podkwerenda w tym przypadku jest znacznie bardziej czytelna. Dziękuję Ci. –

+0

Dzięki za dobrą odpowiedź! Ale co, jeśli sub-select zwraca więcej niż jeden wiersz? Może się zdarzyć, jeśli w którymś węźle znajduje się więcej niż jeden rodzic. Następnie Postgres pokazuje błąd: "więcej niż jeden wiersz zwrócony przez podzapytanie użyte jako wyrażenie" Czy istnieje sposób, aby sobie z tym poradzić? – Johnner

+0

Jak zdefiniowałbyś węzeł z więcej niż jednym rodzicielstwem w ogóle za pomocą zmaterializowanego wzoru ścieżki, którego używa system? –

0

coś takiego:

WITH r AS 
(
    SELECT *, row_number() OVER (ORDER BY path) rn 
     FROM myTree 
) 
SELECT * 
    FROM r 
WHERE rn <= (SELECT rn FROM r WHERE path ~ '*.C'); 

SQL Fiddle

Może istnieje lepszy sposób za pomocą wbudowanego rzeczy jednak.

+0

Dziękuję, to wygląda na dość skomplikowaną dla mojej obecnej wiedzy, ale spróbuję. Obawiam się, że (myślę) ograniczam się do prostych instrukcji zapytań, ponieważ jestem za biblioteką ORM. –

Powiązane problemy