SQL 재 귀적 조회 인 스 턴 스

7514 단어 netkillerPostgreSQL

재 귀적 조회 실례
http://justcramer.com/2010/05/30/scaling-threaded-comments-on-django-at-disqus/
 
	        
create table comments (
    id SERIAL PRIMARY KEY,
    message VARCHAR,
    author VARCHAR,
    parent_id INTEGER REFERENCES comments(id)
);
insert into comments (message, author, parent_id)
    values ('This thread is really cool!', 'David', NULL), ('Ya David, we love it!', 'Jason', 1), ('I agree David!', 'Daniel', 1), ('gift Jason', 'Anton', 2),
    ('Very interesting post!', 'thedz', NULL), ('You sir, are wrong', 'Chris', 5), ('Agreed', 'G', 5), ('Fo sho, Yall', 'Mac', 5);
			
	        
			
WITH RECURSIVE cte (id, message, author, path, parent_id, depth)  AS (
    SELECT  id,
        message,
        author,
        array[id] AS path,
        parent_id,
        1 AS depth
    FROM    comments
    WHERE   parent_id IS NULL

    UNION ALL

    SELECT  comments.id,
        comments.message,
        comments.author,
        cte.path || comments.id,
        comments.parent_id,
        cte.depth + 1 AS depth
    FROM    comments
    JOIN cte ON comments.parent_id = cte.id
    )
    SELECT id, message, author, path, depth FROM cte ORDER BY path;
	    	
			

출력 결과
 id |           message           | author |  path   | depth
----+-----------------------------+--------+---------+-------
  1 | This thread is really cool! | David  | {1}     |     1
  2 | Ya David, we love it!       | Jason  | {1,2}   |     2
  4 | gift Jason                  | Anton  | {1,2,4} |     3
  3 | I agree David!              | Daniel | {1,3}   |     2
  5 | Very interesting post!      | thedz  | {5}     |     1
  6 | You sir, are wrong          | Chris  | {5,6}   |     2
  7 | Agreed                      | G      | {5,7}   |     2
  8 | Fo sho, Yall                | Mac    | {5,8}   |     2
(8 rows)

 
재 귀적 조회 인 스 턴 스 city 표
정의 구조
	    	
CREATE TABLE city
(
  id serial NOT NULL,
  name character varying,
  parent_id integer,
  status boolean,
  CONSTRAINT city_pkey PRIMARY KEY (id),
  CONSTRAINT city_parent_id_fkey FOREIGN KEY (parent_id)
      REFERENCES city (id) MATCH SIMPLE
      ON UPDATE NO ACTION ON DELETE NO ACTION
)
WITH (
  OIDS=FALSE
);
ALTER TABLE city
  OWNER TO sys;
	    	
	    	

데이터 삽입
	    	
INSERT INTO city (id, name, parent_id, status) VALUES (1, '  ', NULL, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (2, '  ', NULL, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (3, '  ', 1, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (4, '  ', 1, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (5, '  ', 3, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (6, '  ', 3, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (7, '  ', 3, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (8, '  ', 7, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (9, '  ', 7, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (10, '  ', 7, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (11, '  ', 2, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (12, '  ', 2, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (13, '  ', 2, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (14, '  ', 13, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (15, '  ', 13, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (16, '   ', NULL, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (17, '  ', 16, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (18, '   ', 16, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (19, '    ', 16, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (20, '   ', 16, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (21, '   ', 16, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (22, '  ', 10, NULL);
INSERT INTO city (id, name, parent_id, status) VALUES (23, '  ', 10, NULL);
	    	
	    	

조회 하 다.
	    	
WITH RECURSIVE path(id, name, path, idpath, parent_id, status) AS (
  SELECT id, name, '/' || name , '/' || id , parent_id, status FROM city WHERE parent_id is null
  UNION
  SELECT
    city.id,
    city.name,
    parentpath.path ||
      CASE parentpath.path
	WHEN '/' THEN ''
	ELSE '/'
      END || city.name,
    parentpath.idpath ||
     CASE parentpath.idpath
	WHEN '/' THEN ''
	ELSE '/'
      END || city.id,
    city.parent_id, city.status
  FROM city, path as parentpath
  WHERE city.parent_id = parentpath.id
)

SELECT * FROM path;
	    	
	    	

결과 출력
	    	
 id |   name   |           path            |    idpath    | parent_id | status
----+----------+---------------------------+--------------+-----------+--------
  1 |        | /                       | /1           |           |
  2 |        | /                       | /2           |           |
 16 |       | /                      | /16          |           |
  3 |        | /  /                  | /1/3         |         1 |
  4 |        | /  /                  | /1/4         |         1 |
 11 |        | /  /                  | /2/11        |         2 |
 12 |        | /  /                  | /2/12        |         2 |
 13 |        | /  /                  | /2/13        |         2 |
 17 |        | /   /                | /16/17       |        16 |
 18 |       | /   /               | /16/18       |        16 |
 19 |      | /   /              | /16/19       |        16 |
 20 |       | /   /               | /16/20       |        16 |
 21 |       | /   /               | /16/21       |        16 |
  5 |        | /  /  /             | /1/3/5       |         3 |
  6 |        | /  /  /             | /1/3/6       |         3 |
  7 |        | /  /  /             | /1/3/7       |         3 |
 14 |        | /  /  /             | /2/13/14     |        13 |
 15 |        | /  /  /             | /2/13/15     |        13 |
  8 |        | /  /  /  /        | /1/3/7/8     |         7 |
  9 |        | /  /  /  /        | /1/3/7/9     |         7 |
 10 |        | /  /  /  /        | /1/3/7/10    |         7 |
 22 |        | /  /  /  /  /   | /1/3/7/10/22 |        10 |
 23 |        | /  /  /  /  /   | /1/3/7/10/23 |        10 |
(23 rows)
	    	

 
 
 

좋은 웹페이지 즐겨찾기