PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

SQL Tìm tất cả con cháu trực tiếp trong một cây

Trong PostgreSQL 8.4 mới bạn có thể làm điều đó với CTE :

WITH RECURSIVE q AS
        (
        SELECT  h, 1 AS level, ARRAY[id] AS breadcrumb
        FROM    t_hierarchy h
        WHERE   parent = 0
        UNION ALL
        SELECT  hi, q.level + 1 AS level, breadcrumb || id
        FROM    q
        JOIN    t_hierarchy hi
        ON      hi.parent = (q.h).id
        )
SELECT  REPEAT('  ', level) || (q.h).id,
        (q.h).parent,
        (q.h).value,
        level,
        breadcrumb::VARCHAR AS path
FROM    q
ORDER BY
        breadcrumb

Xem bài viết này trong blog của tôi để biết chi tiết:

Trong 8.3 hoặc sớm hơn, bạn sẽ phải viết một hàm:

CREATE TYPE tp_hierarchy AS (node t_hierarchy, level INT);

CREATE OR REPLACE FUNCTION fn_hierarchy_connect_by(INT, INT)
RETURNS SETOF tp_hierarchy
AS
$$
        SELECT  CASE
                WHEN node = 1 THEN
                        (t_hierarchy, $2)::tp_hierarchy
                ELSE
                        fn_hierarchy_connect_by((q.t_hierarchy).id, $2 + 1)
                END
        FROM    (
                SELECT  t_hierarchy, node
                FROM    (
                        SELECT  1 AS node
                        UNION ALL
                        SELECT  2
                        ) nodes,
                        t_hierarchy
                WHERE   parent = $1
                ORDER BY
                        id, node
                ) q;
$$
LANGUAGE 'sql';

và chọn từ chức năng này:

SELECT  *
FROM    fn_hierarchy_connect_by(4, 1)

Tham số đầu tiên là id gốc , thứ hai phải là 1 .

Xem bài viết này trong blog của tôi để biết thêm chi tiết:

Cập nhật:

Để chỉ hiển thị các nút con cấp một hoặc chính nút nếu các nút con không tồn tại, hãy đưa ra truy vấn sau:

SELECT  *
FROM    t_hierarchy
WHERE   parent = @start
UNION ALL
SELECT  *
FROM    t_hierarchy
WHERE   id = @start
        AND NOT EXISTS
        (
        SELECT  NULL
        FROM    t_hierarchy
        WHERE   parent = @start
        )

Điều này hiệu quả hơn một JOIN , vì truy vấn thứ hai sẽ thực hiện nhưng chỉ quét tối đa hai chỉ mục:truy vấn đầu tiên để đảm bảo tìm ra con có tồn tại hay không, truy vấn thứ hai để chọn hàng mẹ nếu không có con nào tồn tại.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Toán tử postgres cho kiểu dữ liệu JSON sử dụng Rails 4

  2. pgmemcache so với Infinite Cache

  3. PostgreSQL:Chỉ mục GIN hay GiST?

  4. Làm cách nào để đặt tên thuộc tính chính xác thành kết quả tổng hợp json với mệnh đề GROUP BY?

  5. Các cột MySQL với DEFAULT NULL - sự lựa chọn theo kiểu hay là?