2016-08-07 5 views
0

私はpostgres 9.5を使用しています。私は(のようなツリー)を格納する必要が このようなデータ:テーブル内のSQL階層

  • レベル1A
    • レベル2A
      • レベル3A
      • レベル3B
    • レベル2B
  • レベル1B

    • レベル2aの
    • レベル2bの
  • 1Dレベル1C

  • レベル

これは私のSQLテーブルです:

CREATE TABLE matieres_test ( id serial NOT NULL CONSTRAINT matieres_test_id_pk PRIMARY KEY, name varchar NOT NULL, parent INT DEFAULT NULL, CONSTRAINT matieres_test_parent_fk FOREIGN KEY (parent) REFERENCES matieres_test(id) );

と挿入(集計読みやすい場合)

insert into matieres_test(id,name,parent) values (1,'level 1a',null); 
    insert into matieres_test(id,name,parent) values (5,'level 2a ',1); 
     insert into matieres_test(id,name,parent) values (9,'level 3a',5); 
     insert into matieres_test(id,name,parent) values (10,'level 3b',5); 
    insert into matieres_test(id,name,parent) values (6,'level 2b', 1); 

insert into matieres_test(id,name,parent) values (2,'level 1b',null); 
    insert into matieres_test(id,name,parent) values (7,'level 2a',2); 
    insert into matieres_test(id,name,parent) values (8,'level 2b',2); 

insert into matieres_test(id,name,parent) values (3,'level 1c',null); 
insert into matieres_test(id,name,parent) values (4,'level 1d',null); 

今私は、データを取得したい、私のクエリ:

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4 
FROM matieres_test AS t1 
LEFT JOIN matieres_test AS t2 ON t2.parent = t1.id 
LEFT JOIN matieres_test AS t3 ON t3.parent = t2.id 
LEFT JOIN matieres_test AS t4 ON t4.parent = t3.id 

結果:

| lev1 | lev2  | lev3 
----|-----------|-----------|----------  
1 | level 1a | level 2a | level 3b 
2 | level 1a | level 2a | level 3a 
3 | level 2a | level 3b | 
4 | level 1b | level 2b | 
5 | level 1a | level 2b | 
6 | level 1b | level 2a | 
7 | level 2a | level 3a | 
8 | level 3b | 
9 | level 2b | 
10 | level 2b | 
11 | level 2a | 
12 | level 1d | 
13 | level 1c | 
14 | level 3a | 

問題が

I ...私は "LEV1" 欄などに "レベル2aに" を取得するので、それは(ライン3,7,8,9,10,11,14) を間違った行を返すことです

| lev1 | lev2  | lev3 
----|-----------|-----------|---------- 
    | level 1a | level 2a | level 3a 
    | level 1a | level 2a | level 3b 
    | level 1a | level 2b | 
    | level 1b | level 2a | 
    | level 1b | level 2b | 
    | level 1d | 
    | level 1c | 

どうぞよろしくお願いします。

答えて

1
SELECT DISTINCT 
    t1.name AS lev1, 
    t2.name AS lev2, 
    t3.name AS lev3, 
    t4.name AS lev4 
FROM matieres_test AS t1 
LEFT JOIN matieres_test AS t2 
    ON t2.parent = t1.id 
LEFT JOIN matieres_test AS t3 
    ON t3.parent = t2.id 
LEFT JOIN matieres_test AS t4 
    ON t4.parent = t3.id 
WHERE t1.parent IS NULL 
ORDER BY lev1, lev2, lev3, lev4; 

t1.parentを確認するには、IS NULLチェックを追加する必要があります。与えられたORDER BY句を使用すると、結果を正しく並べ替えることができます。

2

すべてを行う必要がparentとしてnullを持ってlev1を記録するようにクエリを制限しているように見えます:結果になるwhere句を追加した後

SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4 
FROM matieres_test AS t1 
LEFT JOIN matieres_test AS t2 ON t2.parent = t1.id 
LEFT JOIN matieres_test AS t3 ON t3.parent = t2.id 
LEFT JOIN matieres_test AS t4 ON t4.parent = t3.id 
WHERE t1.parent IS NULL -- add this condition 
-- and an optional ORDER BY clause if you need the result in a specific order... 

lev1  lev2  lev3  lev4 
---------- ---------- ---------- ---------- 
level 1a level 2a level 3a NULL 
level 1a level 2a level 3b NULL 
level 1a level 2b NULL  NULL 
level 1b level 2a NULL  NULL 
level 1b level 2b NULL  NULL 
level 1c NULL  NULL  NULL 
level 1d NULL  NULL  NULL 
+0

order by句を追加しないと、結果が異なって見えます。たとえば、最初の行はレベル1b、レベル2b、ヌル、ヌルです。 – mxlse

+0

@mxlseはい、明示的な順序付けを行わなくても、結果セットはほとんど順序付けられません。 – jpw

+1

私に仕事に答えてくれてありがとう。彼はポイントが少ないので、私は他の答えを受け入れる;) – AlainIb