2009-10-21 84 views
8

Mam swój nienajlepszy zagnieżdżone konfiguracji zestaw typu hierarchia z następującymi kolumnami:Zestawy zagnieżdżone MySQL - Jak znaleźć rodzica węzła?

nazwa tabeli:

myset 

kolumny:

id, name, lft, rgt 

Czy ktoś wie zapytanie do określenia rodzic węzła?

Czytałem kilka miejsc, że jest przydatny również mają parent_id kolumna w tabeli, aby śledzić to, ale wydaje się zbędna i wydaje się, że to może wyjść z synchronizacją z zagnieżdżonego zestawu jeśli zapytanie został nieprawidłowo wykonany podczas dodawania/usuwania/przenoszenia dowolnego elementu w zestawie.

Odpowiedz

17

Spójrz na this question. Jest podobny do twojego. Wysłałem tam zapytanie, które możesz potrzebować.

SELECT title, (SELECT TOP 1 title 
      FROM tree t2 
      WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt  
      ORDER BY t2.rgt-t1.rgt ASC) AS parent 
FROM tree t1 
ORDER BY rgt-lft DESC 

Mam nadzieję, że jest to, czego potrzebujesz.

Na poniższej tabeli:

+-------------+----------------------+-----+-----+ 
| category_id | name     | lft | rgt | 
+-------------+----------------------+-----+-----+ 
|   1 | ELECTRONICS   | 1 | 20 | 
|   2 | TELEVISIONS   | 2 | 9 | 
|   3 | TUBE     | 3 | 4 | 
|   4 | LCD     | 5 | 6 | 
|   5 | PLASMA    | 7 | 8 | 
|   6 | PORTABLE ELECTRONICS | 10 | 19 | 
|   7 | MP3 PLAYERS   | 11 | 14 | 
|   8 | FLASH    | 12 | 13 | 
|   9 | CD PLAYERS   | 15 | 16 | 
|   10 | 2 WAY RADIOS   | 17 | 18 | 

produkuje wyjście:

title    | parent 
---------------------------------------------- 
ELECTRONICS   | NULL 
PORTABLE ELECTRONICS | ELECTRONICS 
TELEVISIONS   | ELECTRONICS 
MP3 PLAYERS   | PORTABLE ELECTRONICS 
FLASH    | MP3 PLAYERS 
CD PLAYERS   | PORTABLE ELECTRONICS 
2 WAY RADIOS   | PORTABLE ELECTRONICS 
TUBE     | TELEVISIONS 
LCD     | TELEVISIONS 
PLASMA    | TELEVISIONS 
+0

Czy wiesz, dlaczego 'ORDER BY t2.rgt-t1.rgt' zwróci błąd w sqlite? 'SQLSTATE [HY000]: Błąd ogólny: 1 nie ma takiej kolumny: t1.rgt' ... działa, gdy usuwam t1.rgt z zamówienia, więc wydaje się, że problem z zamówieniem przez ... – Stoner

0

Wszystkie przodkowie są zwracane przez

SELECT id FROM thetable 
WHERE x BETWEEN lft and rgt; 

Tak, bezpośrednio dominującym jest przodkiem z najmniejsza różnica między lft i rgt.

SELECT id FROM thetable 
WHERE x BETWEEN lft and rgt 
ORDER BY (rgt-lft) 
LIMIT 1 
+1

jeśli twój x powinien być id elementu, niż twoje oświadczenia są błędne. – spankmaster79

2

Miałem problem z zapytaniem Lucasza. Moja wersja mysql nie zrozumiała polecenia TOP. Zamiast tego musiałem użyć LIMIT. Oto poprawiony kod.

SELECT 
    `id`, 
    (SELECT 
     `id` 
    FROM 
     `[*** YOUR TABLE ***]` AS `t2` 
    WHERE 
     `t2`.`left_id` < `t1`.`left_id`AND 
     `t2`.`right_id` > `t1`.`right_id` 
    ORDER BY 
     `t2`.`right_id`-`t1`.`right_id`ASC 
    LIMIT 
     1) AS `parent` 
FROM 
    `[*** YOUR TABLE ***]` AS `t1` 
WHERE 
    `t1`.`id` = [*** ID OF THE NODE WHOS PARENT YOU WISH TO LOOKUP ***] 
ORDER BY 
    `right_id`-`left_id` DESC 

Oczywiście, zmień rzeczy w [] w zależności od potrzeb. Usuń także []. To zapytanie zwraca tylko JEDEN wiersz. Podobnie jak ...

id parent 
7 3 
14

TOP jest polecenie MSSQL, użycie LIMIT dla MySQL:

SELECT title, (SELECT title 
     FROM tree t2 
     WHERE t2.lft < t1.lft AND t2.rgt > t1.rgt  
     ORDER BY t2.rgt-t1.rgt ASC 
     LIMIT 1) 
AS parent FROM tree t1 
ORDER BY (rgt-lft) DESC 

powinno załatwić sprawę ..

0

Kod z spankmaster79 nie był całkowicie błędne. Zmodyfikowałem jego kod i zadziałało.

SELECT parent . * FROM Nested_Category AS node, Nested_Category AS parent 
enter code hereWHERE node.leftSide 
BETWEEN parent.leftSide 
AND parent.rightSide 
AND node.id ='Enter the Node ID' 
ORDER BY (
parent.rightSide - parent.leftSide 
) 
LIMIT 1 , 1 
0
select * from myset 
    where lft < :lftOfCurrent and rgt > :lftOfCurrent 
    order lft desc 
    limit 1 

Można użyć max zamiast zlecenia/limitu i może trzeba innego słowa kluczowego, aby ograniczyć wyniki do jednego wiersza w zależności od bazy danych. Pomiędzy raczej niż < i> działałoby, gdyby baza danych zwróciła ekskluzywny zestaw, którego MySQL nie ma.

3

tylko dodać do tych odpowiedzi, które pomogły mi się dużo,

Musiałem znaleźć bezpośredniego rodzica węzła, a także bardzo najwyższego poziomu rodzica łańcucha węzłów w niektórych przypadkach

użyłem następujących jako podstawa do uzyskania produktów w dziecko-to-rodzica aby

SELECT parent.* FROM 
     nested_set node, 
     nested_set parent 
     WHERE (
      node.set_left BETWEEN parent.set_left AND parent.set_right   
     ) 
     AND node.set_id={CHILD_NODE_ID_HERE} 
     ORDER BY parent.set_right - parent.set_left 
     #LIMIT 1,1 

to wówczas kwestia dodawania LIMIT 1,1 tylko uchwycić drugiego rzędu, które byłyby natychmiastowe rodzic

należy również zauważyć, że z powyższego zapytania jeśli sam węzeł jest bardzo najwyższym poziomie rodzic, to nie byłoby to bezpośredniego rodzica, więc z LIMIT 1,1 powinien powrócić pusty zestaw wyników

aby uzyskać bardzo najwyższego poziomu rodzica i odwróceniu kolejności przez klauzuli zawarte czek jeśli sam węzeł jest najlepszym rodzicem, a ogranicza wynik do pierwszego rzędu

SELECT parent.* AS top_level_right FROM 
     nested_set node, 
     nested_set parent 
     WHERE (
      node.set_left >= parent.set_left 
      AND node.set_left <= parent.set_right 
     ) 
     AND node.set_id={CHILD_NODE_ID_HERE} 
     ORDER BY parent.set_left - parent.set_right 
     LIMIT 1 

w ostatnim zapytaniu użyłem >= <= operatorzy tak że wybrany zakres obejmuje węzeł potomny, jeśli tak się dzieje być rodzicem najwyższego poziomu

1
SELECT parent.name 
FROM myset AS node, myset AS parent 
WHERE parent.lft < node.lft 
AND parent.rgt > node.rgt 
AND node.id = {YOUR CATEGORY ID} 
ORDER BY (parent.rgt - parent.lft) ASC LIMIT 1;