2012-04-02 11 views
1

Ich habe eine Tabelle Benutzer, in denen ich ein Feld "ID" und ein anderes Feld ist "Eltern-ID". Auch habe ich Zielfeld in der Benutzertabelle erwartet.Multilevel-Benutzer in der Datenbanktabelle

Ich habe eine Liste von Benutzern bis zur 8. Ebene Hierarchie. Wo A ist Elternteil von B und B ist Elternteil von C und so weiter.

beispiels

A level 0 
| 
B level 1 
| 
c level 2 

Wenn ich jetzt für Benutzer A. suchen möchte ich die alle Unter Benutzer unter Verwendung von SQL-Abfrage ‚Ziel erwartet‘ erhalten. dh wenn I = ID verwenden ID eines dann kann ich das erwartete Ziel von A, B sehen, C usw.

Wenn expected_targets für A, B und C werden in 1000, 500, 200 jeweils die Ausgabe sein sollte:

id  parent_id  expected_target 

A_id      1000 
B_id  A_id   500 
C_id  B_id   200 
+0

Ist diese Datenbankstruktur "gesperrt"? Ich kann mir keinen performanten Weg vorstellen, dies mit Standard-SQL zu tun (7-Stufen-Self-Joins ist nicht etwas, was ich vorschlagen würde) –

+0

Es sieht aus wie die Art von Problem, dass der [ltree] (http: //www.postgresql. org/docs/current/static/ltree.html) Modul soll lösen –

+0

@JoachimIsaksson was ist falsch mit 7 selbst verbindet .. es ist völlig in Ordnung, wenn die Anzahl der Ebenen ist garantiert;) aber ich verstehe nicht, was ist das * erwartetes Ziel * - sollten die Ergebnisse in Zeilen oder Spalten sein? – Aprillion

Antwort

1

dies wird den Job - http://sqlfiddle.com/#!2/0de1f/7:

select u1.id, u1.parent_id, u1.expected_target 
from users u1 
left join users u2 on u1.parent_id = u2.id 
left join users u3 on u2.parent_id = u3.id 
left join users u4 on u3.parent_id = u4.id 
left join users u5 on u4.parent_id = u5.id 
left join users u6 on u5.parent_id = u6.id 
left join users u7 on u6.parent_id = u7.id 
left join users u8 on u7.parent_id = u8.id 
where :A_id in (u1.id, u2.id, u3.id, u4.id, u5.id, 
       u6.id, u7.id, u8.id, u8.parent_id) 
1
SET search_path='tmp'; 

DROP TABLE targets CASCADE; 
CREATE TABLE targets 
     (id integer not null primary key 
     , parent_id integer references targets(id) 
     , expected_target integer 
     ); 

INSERT INTO targets(id,parent_id,expected_target) VALUES 
(1,NULL, 1000), (2,1, 500), (3,2, 200); 


WITH RECURSIVE zzz AS (
     SELECT t0.id, t0.parent_id 
     , 0::integer AS level 
     , t0.expected_target 
     FROM targets t0 
     WHERE t0.parent_id IS NULL 
     UNION 
     SELECT t1.id, t1.parent_id 
     , 1+zzz.level AS level 
     , t1.expected_target 
     FROM targets t1 
     JOIN zzz ON zzz.id = t1.parent_id 
     ) 
SELECT * FROM zzz 
     ; 

OUTPUT:

SET 
DROP TABLE 
NOTICE: CREATE TABLE/PRIMARY KEY will create implicit index "targets_pkey" for table "targets" 
CREATE TABLE 
INSERT 0 3 
id | parent_id | level | expected_target 
----+-----------+-------+----------------- 
    1 |   |  0 |   1000 
    2 |   1 |  1 |    500 
    3 |   2 |  2 |    200 
(3 rows) 

UPDATE: wenn Sie nicht wollen, den ganzen Baum, den wahren Baum und nichts als den Baum aber nur ein Teilbaum eines Teil davon, können Sie natürlich auch die Bedingungen ein wenig ändern:

WITH RECURSIVE zzz AS (
     SELECT t0.id, t0.parent_id 
     , 0::integer AS level 
     , t0.expected_target 
     FROM targets t0 
     -- WHERE t0.parent_id IS NULL 
     WHERE t0.id = 2 
     UNION 
     SELECT t1.id, t1.parent_id 
     , 1+zzz.level AS level 
     , t1.expected_target 
     FROM targets t1 
     JOIN zzz ON zzz.id = t1.parent_id 
     ) 
SELECT * FROM zzz 
     ; 
+0

+1 Ich wusste nicht dort muss RECURSIVE Keyword sein;) – Aprillion

+0

Diese Abfrage ist gut, aber wenn ich die Ergebnisse von ID 2 sehen möchte, dann wie kann ich diese Abfrage schreiben.Ich habe versucht WHERE t0.id = 2 anstelle von WHERE t0.parent_id IS NULL aber die Abfrage läuft einfach ohne Ausgabe –

+0

Was meinen Sie mit "die Ergebnisse für ID 2"? Nur ID = 2? (Scheint trivial) ID = 2; einschließlich Kinder a Enkel und vollständige Nachkommen? – wildplasser

0

Da dies mit PostgreSQL dem Stichwort:

with recursive users_tree as (
    select id, 
     parent_id, 
     expected_target, 
     1 as level 
    from users 
    where id = 'A_id' 

    union all 

    select c.id, 
     c.parent_id, 
     c.expected_target, 
     p.level + 1 
    from users c 
    join users_tree p on c.parent_id = p.id 
) 
select * 
from users_tree 

MySQL nicht weit genug fortgeschritten ist, dies zu unterstützen. Dort müssen Sie für jeden Level einen Self-Join durchführen.

+0

Diese Abfrage kann nicht ausgeführt werden, da sie weiter ausgeführt wird. –

+0

@SuryawanshiManoj: Dann haben Sie offensichtlich einige Zyklen in Ihren Daten (eine ID, die auf einen Elternteil zeigt, der auf die ID selbst verweist - vielleicht über mehrere Ebenen hinweg) –

Verwandte Themen