SlideShare a Scribd company logo
1 of 128
Trees in the Database
       Advanced Data Structures




        Lorenzo Alberton
           lorenzo@ibuildings.com
  DPC09, Amsterdam, 13 June 2009
Lorenzo Alberton




                   2
Lorenzo Alberton

                   MDB2
                   Calendar
                   Pager
                   Translation2
                   Mail_Queue
                   DB_QueryTool




                                  2
Lorenzo Alberton

                   MDB2
                   Calendar
                   Pager
                   Translation2
                   Mail_Queue
                   DB_QueryTool




                                  2
Tree

Connected, undirected, acyclic graph


                       A

                 B           C             G

                       D               E


                                       F

                                               3
Tree

Connected, undirected, acyclic graph


                       A

                 B           C

                       D               E


                                       F

                                           3
Tree

Connected, undirected, acyclic graph


                       A

                 B           C

                       D               E


                                       F

                                           3
Tree

Connected, undirected, acyclic graph


                       A

                 B           C

                       D               E


                                       F

                                           3
Tree

Connected, undirected, acyclic graph


                       A

                 B           C

                       D               E


                                       F

                                           3
Adjacency List Model
AKA “parent-child” model




                           4
Adjacency List Model

CREATE TABLE emp_orgchart (
    emp VARCHAR(10) NOT NULL PRIMARY KEY,
    boss VARCHAR(10),
    salary DECIMAL(6,2) NOT NULL
);

                                     A
  emp    boss   salary
   A     NULL   1000.00
                            B               C
   B      A     900.00
   C      A     900.00
   D      C     800.00           D          E   F
   E      C     700.00
   F      C     600.00

                                                    5
Adjacency List Model

  Finding the root node

     SELECT *
       FROM emp_orgchart
      WHERE boss IS NULL;


  Finding the leaf nodes

     SELECT   e1.*
       FROM   emp_orgchart AS e1
  LEFT JOIN   emp_orgchart AS e2 ON e1.emp = e2.boss
      WHERE   e2.emp IS NULL;




                                                   6
Adjacency List Model Anomalies

UPDATE anomalies

  START TRANSACTION;
                         emp     boss   salary
  UPDATE emp_orgchart     A      NULL   1000.00
     SET emp = ‘C1’       B       A     900.00
   WHERE emp = ‘C’;       C1      A     900.00
                          D       C     800.00
  UPDATE emp_orgchart     E       C     700.00
     SET boss = ‘C1’      F       C     600.00
   WHERE boss = ‘C’;

  COMMIT;


                                                  7
Adjacency List Model Anomalies

UPDATE anomalies

  START TRANSACTION;
                         emp     boss   salary
  UPDATE emp_orgchart     A      NULL   1000.00
     SET emp = ‘C1’       B       A     900.00
   WHERE emp = ‘C’;       C1      A     900.00
                          D       C     800.00
  UPDATE emp_orgchart     E       C     700.00
     SET boss = ‘C1’      F       C     600.00
   WHERE boss = ‘C’;

  COMMIT;


                                                  7
Adjacency List Model Anomalies

UPDATE anomalies

  START TRANSACTION;
                        UPDATE emp_orgchart
                           SET emp = CASE emp
  UPDATE emp_orgchart
                                WHEN ‘C’ THEN ‘C1’
     SET emp = ‘C1’
                                ELSE emp END,
   WHERE emp = ‘C’;
                               boss = CASE boss
                                WHEN ‘C’ THEN ‘C1’
  UPDATE emp_orgchart
                                ELSE boss END
     SET boss = ‘C1’
                         WHERE ‘C’ IN (emp, boss);
   WHERE boss = ‘C’;

  COMMIT;


                                                 7
Adjacency List Model Anomalies

INSERT anomalies




                                 8
Adjacency List Model Anomalies

INSERT anomalies

  INSERT INTO emp_orgchart (emp, boss) VALUES
  (‘G’, ‘H’),
  (‘H’, ‘G’);

                   G         H




                                                8
Adjacency List Model Anomalies

INSERT anomalies

  INSERT INTO emp_orgchart (emp, boss) VALUES
  (‘G’, ‘H’),
  (‘H’, ‘G’);

                   G         H



  INSERT INTO emp_orgchart VALUES (‘M’, ‘M’);


                       M


                                                8
Adjacency List Model Anomalies

DELETE anomalies



   DELETE FROM emp_orgchart WHERE emp = ‘C’;




                       A


              B            C


                   D       E     F

                                               9
Adjacency List Model Anomalies

DELETE anomalies



   DELETE FROM emp_orgchart WHERE emp = ‘C’;




                       A


              B            C


                   D       E     F

                                               9
Fixing the Adjacency List Model
 CREATE TABLE emp (
    id INTEGER DEFAULT 0   PRIMARY KEY,
    name VARCHAR(10) NOT   NULL,
    salary DECIMAL (6,2)   NOT NULL
        CHECK (salary >=   0.00),
    ...
 );

 CREATE TABLE orgchart (
    emp_id INTEGER NOT NULL DEFAULT 0 -- vacant
        REFERENCES emp(id)
        ON DELETE SET DEFAULT ON UPDATE CASCADE,
    boss_id INTEGER -- NULL means root node
        REFERENCES emp(id),
    ...
 );

                                                   10
Fixing the Adjacency List Model

 -- cannot be your own boss
 CHECK ((boss_id <> emp_id) OR
        (boss_id = 0 AND emp_id = 0)),




                                         11
Fixing the Adjacency List Model

 -- cannot be your own boss
 CHECK ((boss_id <> emp_id) OR
        (boss_id = 0 AND emp_id = 0)),

 -- prevent longer cycles
 UNIQUE (emp_id, boss_id),




                                         11
Fixing the Adjacency List Model

 -- cannot be your own boss
 CHECK ((boss_id <> emp_id) OR
        (boss_id = 0 AND emp_id = 0)),

 -- prevent longer cycles
 UNIQUE (emp_id, boss_id),

 -- connected graph (edges = nodes - 1)
 CHECK ((SELECT COUNT(*) FROM orgchart) - 1
      = (SELECT COUNT(boss_id) FROM orgchart)),




                                                  11
Fixing the Adjacency List Model

 -- cannot be your own boss
 CHECK ((boss_id <> emp_id) OR
        (boss_id = 0 AND emp_id = 0)),

 -- prevent longer cycles
 UNIQUE (emp_id, boss_id),

 -- connected graph (edges = nodes - 1)
 CHECK ((SELECT COUNT(*) FROM orgchart) - 1
      = (SELECT COUNT(boss_id) FROM orgchart)),

 -- one root only
 CHECK ((SELECT COUNT(*) FROM orgchart WHERE
 boss_id IS NULL) = 1),


                                                  11
Adjacency List Model - Navigation



 Loops /               Self-Joins
 procedural code
                       SELECT o1.emp AS e1,
                              o2.emp AS e2,
 CREATE PROCEDURE
                              o3.emp AS e3
 TreeTraversal (IN
                         FROM emp_orgchart AS o1
 current_emp_id INT)
                         LEFT OUTER JOIN
 BEGIN
                              emp_orgchart AS o2
 ...
                           ON o1.emp = o2.boss
                         LEFT OUTER JOIN
                              emp_orgchart AS o3
                           ON o2.emp = o3.boss
                       WHERE o1.emp = ‘A’;
                                                   12
Adjacency List Model - Deletion




                                  13
Adjacency List Model - Deletion




           A


   B           C



       D       E   F




                                  13
Adjacency List Model - Deletion




           A


   B           C



       D
               x
               E   F




                                  13
Adjacency List Model - Deletion




           A                   A


   B           C       B           C



       D
               x
               E   F       D       E   F




                                           13
Adjacency List Model - Deletion




           A                       A

                                       A
   B           C           B               C



       D
               x
               E   F
                       B       D
                               D
                                           E
                                           E
                                               F
                                               F




                                                   13
Adjacency List Model - Deletion




           A                       A                       A

                                       A
   B           C           B               C       B           C



       D
               x
               E   F
                       B       D
                               D
                                           E
                                           E
                                               F
                                               F       D       E   F




                                                                       13
Adjacency List Model - Deletion




           A                       A                       A

                                       A
   B           C           B               C       B           D
                                                               C



       D
               x
               E   F
                       B       D
                               D
                                           E
                                           E
                                               F
                                               F       D       E   F




                                                                       13
Adjacency List Model - Deletion




           A                               A                       A

                                               A
   B           C                   B               C       B           D
                                                                       C



       D
               x
               E       F
                               B       D
                                       D
                                                   E
                                                   E
                                                       F
                                                       F       D       E   F




                   Requires traversal (deferred constraints)

                                                                               13
Path Enumeration Model
aka Materialized Path




                         14
Path Enumeration Model

CREATE TABLE emp_orgchart (
  emp_id CHAR(1) NOT NULL PRIMARY KEY
    -- if using a separator, don’t use it in the ID
    CHECK (REPLACE(emp_id, ‘/’, ‘’) = emp_id),
  emp_name VARCHAR(10) NOT NULL,
  path_string VARCHAR(512) NOT NULL
);


 emp_id   emp_name   path_string           A
   A      Anthony    A
   B      Beryl      AB
                                   B           C
   C      Charles    AC
   D      Denise     ACD
   E      Ellen      ACE               D       E   F
   F      Frank      ACF
                                                       15
Path Enumeration Model

 -- prevent cycles (nodes appearing twice: ‘ABCA’)
 CHECK (NOT EXISTS(
 SELECT *
    FROM emp_orgchart AS D1,
         emp_orgchart AS P1
  WHERE LENGTH(REPLACE(P1.path_string, D1.emp_id,
         ‘’)) <
        LENGTH(P1.path_string) - LENGTH(D1.emp_id))
 ))


 -- No path can be longer than the number of nodes
 CHECK((SELECT MAX(LENGTH(path_string))
          FROM emp_orgchart AS E1) <=
       (SELECT COUNT(emp_id) * LENGTH(emp_id)
          FROM emp_orgchart AS E2))

                                                 16
Path Enumeration Model




                         17
Path Enumeration Model

  Depth of the node




                         17
Path Enumeration Model

  Depth of the node
  • LENGTH(path_string) / LENGTH(emp_id)




                                           17
Path Enumeration Model

  Depth of the node
  • LENGTH(path_string) / LENGTH(emp_id)
  • LENGTH(path_string) -
    LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1




                                                17
Path Enumeration Model

  Depth of the node
  • LENGTH(path_string) / LENGTH(emp_id)
  • LENGTH(path_string) -
    LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1




                                                17
Path Enumeration Model

  Depth of the node
  • LENGTH(path_string) / LENGTH(emp_id)
  • LENGTH(path_string) -
    LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1


  Searching for subordinates




                                                17
Path Enumeration Model

  Depth of the node
  • LENGTH(path_string) / LENGTH(emp_id)
  • LENGTH(path_string) -
    LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1


  Searching for subordinates
  • SELECT * FROM emp_orgchart
    WHERE path_string LIKE ‘%’ || :parent_emp_id ||
    ‘%’;




                                                      17
Path Enumeration Model

  Depth of the node
  • LENGTH(path_string) / LENGTH(emp_id)
  • LENGTH(path_string) -
    LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1


  Searching for subordinates
  • SELECT * FROM emp_orgchart
    WHERE path_string LIKE ‘%’ || :parent_emp_id ||
    ‘%’;
  • SELECT * FROM emp_orgchart
    WHERE path_string LIKE
      (SELECT path_string FROM emp_orgchart
        WHERE emp_id = :parent_emp_id)        || ‘%’;

                                                      17
Path Enumeration Model

  Searching for superiors

 SELECT SUBSTRING(P1.path_string
        FROM seq * LENGTH(P1.emp_id)
        FOR LENGTH(P1.emp_id)) AS emp_id
   FROM emp_orgchart AS P1,
        sequence AS S1
  WHERE P1.emp_id = :search_emp_id
    AND S1.seq <= LENGTH(path_string)/
                  LENGTH(emp_id);




                                           18
Path Enumeration Model

  Deleting a subtree:

  DELETE FROM emp_orgchart
   WHERE path_string LIKE (
         SELECT path_string
           FROM emp_orgchart
          WHERE emp_id = :deleted_node) || ‘%’;

  Deleting a single node:
     START TRANSACTION;
    DELETE FROM emp_orgchart
     WHERE emp_id = :deleted_node;
    UPDATE emp_orgchart SET path_string =
           REPLACE(path_string, :deleted_node, ‘’);
    COMMIT;
                                                      19
Path Enumeration Model

  Insertion of a new node
  INSERT INTO emp_orgchart VALUES (
    :new_emp_id, -- ‘M’
    :new_name,   -- ‘Maggie’
    (SELECT path_string
       FROM emp_orgchart
      WHERE emp_id = :boss_of_new_emp) -- ‘D’
      || :new_emp_id -- ‘M’
  );

            emp_id   emp_name   path_string

              D      Denise     ACD

              M      Maggie     ACDM

                                                20
Path Enumeration Model

  Insertion of a new node
  INSERT INTO emp_orgchart VALUES (
    :new_emp_id, -- ‘M’
    :new_name,   -- ‘Maggie’
    (SELECT path_string
       FROM emp_orgchart
      WHERE emp_id = :boss_of_new_emp) -- ‘D’
      || :new_emp_id -- ‘M’
  );

            emp_id   emp_name   path_string

              D      Denise     ACD

              M      Maggie     ACDM

                                                20
Path Enumeration Model

  Insertion of a new node
  INSERT INTO emp_orgchart VALUES (
    :new_emp_id, -- ‘M’
    :new_name,   -- ‘Maggie’
    (SELECT path_string
       FROM emp_orgchart
      WHERE emp_id = :boss_of_new_emp) -- ‘D’
      || :new_emp_id -- ‘M’
  );

            emp_id   emp_name   path_string

              D      Denise     ACD

              M      Maggie     ACDM

                                                20
Path Enumeration Model

  Splitting the path string into nodes
  SELECT CASE
         WHEN SUBSTRING(‘/’ || P1.path_string || ‘/’
              FROM S1.seq FOR 1) = ‘/’
         THEN SUBSTRING(‘/’ || P1.path_string || ‘/’
              FROM (S1.seq + 1)
              FOR CharIndex(‘/’ ,
                  ‘/’ || P1.path_string || ‘/’,
                  S1.seq + 1) - S1.seq - 1
         ELSE NULL END AS emp_id
    FROM sequence AS S1,
         emp_orgchart AS P1
   WHERE S1.seq BETWEEN 1
         AND LENGTH(P1.path_string) + 1
     AND SUBSTRING(‘/’ || P1.path_string || ‘/’
         FROM S1.seq FOR 1) = ‘/’
                                                   21
Path Enumeration Model


    emp_name      edge_path           Edge
 Anthony       1.
 Beryl         1.1.
                                      Enumeration
 Charles       1.2.                   Model
 Denise        1.2.1.
 Ellen         1.2.2.
 Frank         1.2.3.
                                      Anthony


                              Beryl             Charles


                                      Denise     Ellen    Frank

                                                                  22
Nested Set Model
aka Modified Preorder Tree Traversal (MPTT)




                                              23
Nested Set Model

                       A
                           C
            B      D       E   F




                                   24
Nested Set Model

                           A
                                   C
             B         D           E       F




                           A
 1                                                               12
         B                             C
     2       3 4                                            11
                       D               E           F
                   5           6   7       8   9       10

                                                                  24
Nested Set Model

CREATE TABLE orgchart (
    emp VARCHAR(10) NOT NULL PRIMARY KEY,
    lft INTEGER NOT NULL,
    rgt INTEGER NOT NULL
);                                   A
                       1                                                       12
                               B                       C
                           2       3 4                                    11
                                             D         E         F
                                         5       6 7       8 9       10




                                                                               25
Nested Set Model

    CREATE TABLE orgchart (
        emp VARCHAR(10) NOT NULL PRIMARY KEY,
        lft INTEGER NOT NULL,
        rgt INTEGER NOT NULL
    );                                   A
                                                1                                                        12
                                                         B                       C
           1           A           12               2        3 4                                    11
                                                                       D         E         F
                                                                   5       6 7       8 9       10

2      B       3               4        C       11




                   D                    E                F
           5               6       7        8        9       10

                                                                                                         25
Nested Set Model
  Finding root node


                              1           A           12




                      2   B       3               4        C       11




                                      D                    E                F
                              5               6       7        8        9       10




                                                                                26
Nested Set Model
  Finding root node
  SELECT *
     FROM orgchart
    WHERE lft = 1;            1           A           12




                      2   B       3               4        C       11




                                      D                    E                F
                              5               6       7        8        9       10




                                                                                26
Nested Set Model
  Finding root node
  SELECT *
     FROM orgchart
    WHERE lft = 1;             1           A           12


  Finding leaf nodes
                       2   B       3               4        C       11




                                       D                    E                F
                               5               6       7        8        9       10




                                                                                 26
Nested Set Model
  Finding root node
  SELECT *
     FROM orgchart
    WHERE lft = 1;              1           A           12


  Finding leaf nodes
  SELECT *
                        2   B       3               4        C       11

    FROM orgchart
   WHERE lft = (rgt - 1);
                                        D                    E                F
                                5               6       7        8        9       10




                                                                                  26
Nested Set Model
  Finding root node
  SELECT *
     FROM orgchart
    WHERE lft = 1;              1           A           12


  Finding leaf nodes
  SELECT *
                        2   B       3               4        C       11

    FROM orgchart
   WHERE lft = (rgt - 1);
                                        D                    E                F
  Finding subtrees              5               6       7        8        9       10




                                                                                  26
Nested Set Model
  Finding root node
  SELECT *
     FROM orgchart
    WHERE lft = 1;                  1           A           12


  Finding leaf nodes
  SELECT *
                          2   B         3               4        C       11

    FROM orgchart
   WHERE lft = (rgt - 1);
                                            D                    E                F
  Finding subtrees                  5               6       7        8        9       10

  SELECT Mgrs.emp AS   boss
         Workers.emp   AS worker
    FROM orgchart AS   Mgrs,
         orgchart AS   Workers
   WHERE Workers.lft   > Mgrs.lft
     AND Workers.lft   < Mgrs.rgt
                                                                                      26
Nested Set Model
  Finding root node
  SELECT *
     FROM orgchart
    WHERE lft = 1;                1           A           12


  Finding leaf nodes
  SELECT *
                          2   B       3               4        C       11

    FROM orgchart
   WHERE lft = (rgt - 1);
                                          D                    E                F
  Finding subtrees                5               6       7        8        9       10

  SELECT Mgrs.emp AS   boss
         Workers.emp   AS worker
    FROM orgchart AS   Mgrs,
         orgchart AS   Workers
   WHERE Workers.lft   > Mgrs.lft
                       BETWEEN Mgrs.lft AND Mgrs.rgt
     AND Workers.lft   < Mgrs.rgt
                                                                                    26
Nested Set Model
  Finding the level of a node




                                27
Nested Set Model
  Finding the level of a node
    SELECT o2.emp,
           COUNT(o1.emp) AS lvl
      FROM orgchart AS o1,
           orgchart AS o2
     WHERE o2.lft BETWEEN o1.lft AND o1.rgt
  GROUP BY o2.emp;




                                              27
Nested Set Model
  Finding the level of a node
    SELECT o2.emp,
           COUNT(o1.emp) AS lvl
      FROM orgchart AS o1,
           orgchart AS o2
     WHERE o2.lft BETWEEN o1.lft AND o1.rgt
  GROUP BY o2.emp;

  Finding the height of the tree




                                              27
Nested Set Model
  Finding the level of a node
    SELECT o2.emp,
           COUNT(o1.emp) AS lvl
      FROM orgchart AS o1,
           orgchart AS o2
     WHERE o2.lft BETWEEN o1.lft AND o1.rgt
  GROUP BY o2.emp;

  Finding the height of the tree
  SELECT MAX(lvl) AS height FROM (
    SELECT o2.emp,
           COUNT(o1.emp) - 1
      FROM orgchart AS o1,
           orgchart AS o2
     WHERE o2.lft BETWEEN o1.lft AND o1.rgt
  GROUP BY o2.emp) AS L1(emp, lvl);

                                              27
Nested Set Model
 Finding relative position
  SELECT CASE
           WHEN :emp1 = :emp2
           THEN :emp1 || ‘ is ’ || :emp2

           WHEN o1.lft BETWEEN o2.lft AND o2.rgt
           THEN :emp1 || ‘ subordinate to ’ || :emp2

           WHEN o2.lft BETWEEN o1.lft AND o1.rgt
           THEN :emp2 || ‘ subordinate to ’ || :emp1

           ELSE :emp1 || ‘ no relation to ’ || :emp2
         END
    FROM orgchart AS o1,
         orgchart AS o2
   WHERE o1.emp = :emp1 AND o2.emp = :emp2;
                                                       28
Nested Set Model
  Deleting subtrees
  DELETE FROM orgchart
   WHERE lft BETWEEN (SELECT      lft
                           FROM   orgchart
                          WHERE   emp = :start_node)
                    AND (SELECT   rgt
                           FROM   orgchart
  Filling gaps            WHERE   emp = :start_node);
 CREATE VIEW   LftRgt (seq) AS
      SELECT   lft FROM orgchart
       UNION   ALL
      SELECT   rgt FROM orgchart;

 UPDATE orgchart SET
 lft = (SELECT COUNT(*) FROM LftRgt WHERE seq <= lft),
 rgt = (SELECT COUNT(*) FROM LftRgt WHERE seq <= rgt)

                                                        29
Nested Set Model
  Deleting a single node

  DELETE FROM orgchart
  WHERE emp = ‘C’;



                               A
                                   C
                B          D       E   F




                                           30
Nested Set Model
  Deleting a single node

  DELETE FROM orgchart
  WHERE emp = ‘C’;



                               A

                B          D       E   F




                                           30
Nested Set Model
  Deleting a single node
  CREATE PROCEDURE downsize(IN removed VARCHAR(10))
  LANGUAGE SQL DETERMINISTIC
  UPDATE orgchart SET emp = CASE
    WHEN orgchart.emp = removed
         AND orgchart.lft + 1 = orgchart.rgt --leaf
    THEN ‘{vacant}’
    WHEN orgchart.emp = removed
         AND orgchart.lft + 1 <> orgchart.rgt
              -- promote subordinate and vacate
    THEN (SELECT o1.emp
            FROM orgchart AS o1
           WHERE orgchart.lft + 1 = o1.lft)
    WHEN orgchart.emp = (SELECT o1.emp
            FROM orgchart AS o1
           WHERE orgchart.lft + 1 = o1.lft)
    THEN ‘{vacant}’ ELSE emp END;
                                                  31
Nested Set Model
  Deleting a single node
  CREATE PROCEDURE downsize(IN removed VARCHAR(10))
  LANGUAGE SQL DETERMINISTIC
  UPDATE orgchart SET emp = CASE
    WHEN orgchart.emp = removed
         AND orgchart.lft + 1 = orgchart.rgt --leaf
    THEN ‘{vacant}’
    WHEN orgchart.emp = removed
         AND orgchart.lft + 1 <> orgchart.rgt
              -- promote subordinate and vacate
    THEN (SELECT o1.emp
            FROM orgchart AS o1
           WHERE orgchart.lft + 1 = o1.lft)
    WHEN orgchart.emp = (SELECT o1.emp
            FROM orgchart AS o1
           WHERE orgchart.lft + 1 = o1.lft)
    THEN ‘{vacant}’ ELSE emp END;
                                                  31
Nested Set to Adjacency List
  SELECT B.id AS boss,
         P.emp, P.lft, P.rgt
    FROM orgchart as P
    LEFT OUTER JOIN emp AS B ON B.lft =
         (SELECT MAX(S.lft)
            FROM orgchart AS S
           WHERE P.lft > S.lft
             AND P.lft < S.rgt);

              boss       emp     lft       rgt
             NULL      Anthony         1         12
             Anthony   Beryl           2          3
             Anthony   Charles         4         11
             Charles   Denise          5          6
             Charles   Ellen           7          8
             Charles   Frank           9         10

                                                      32
Frequent Insertion Trees

Avoid overhead (locking + updating) with larger spreads
and bigger gaps

               emp      lft         rgt
           Anthony            100      1200
           Beryl              200       300
           Charles            400      1100
           Denise             500       600
           Ellen              700       800
           Frank              900      1000




                                                          33
Frequent Insertion Trees

Avoid overhead (locking + updating) with larger spreads
and bigger gaps

               emp      lft         rgt
           Anthony            100      1200
           Beryl              200       300
           Charles            400      1100
           Denise             500       600
           Ellen              700       800
           Frank              900      1000

       Datatype of (lft, rgt)?
       - INTEGER (full range)
       - FLOAT / REAL / DOUBLE
       - NUMERIC(p,s) / DECIMAL(p,s)
                                                          33
Frequent Insertion Trees

Avoid overhead (locking + updating) with larger spreads
and bigger gaps

               emp      lft         rgt
           Anthony            100      1200
           Beryl              200       300
           Charles            400      1100
           Denise             500       600
           Ellen              700       800
           Frank              900      1000

       Datatype of (lft, rgt)?
       - INTEGER (full range)
       - FLOAT / REAL / DOUBLE
       - NUMERIC(p,s) / DECIMAL(p,s)
                                                          33
Frequent Insertion Trees

Avoid overhead (locking + updating) with larger spreads
and bigger gaps

               emp      lft         rgt
           Anthony            100      1200
           Beryl              200       300
           Charles            400      1100
           Denise             500       600
           Ellen              700       800
           Frank              900      1000

       Datatype of (lft, rgt)?
       - INTEGER (full range)
       - FLOAT / REAL / DOUBLE
       - NUMERIC(p,s) / DECIMAL(p,s)
                                                          33
Frequent Insertion Trees

Avoid overhead (locking + updating) with larger spreads
and bigger gaps

               emp      lft         rgt
           Anthony            100      1200
           Beryl              200       300
           Charles            400      1100
           Denise             500       600
           Ellen              700       800
           Frank              900      1000

       Datatype of (lft, rgt)?
       - INTEGER (full range)
       - FLOAT / REAL / DOUBLE
       - NUMERIC(p,s) / DECIMAL(p,s)
                                                          33
Hybrid Models

  Adjacency List with Nested Sets (node, parent, lft, rgt)
  Nested Sets with depth
  Adjacency List with depth
  ...




                Denormalisation to save
                subselects or joins



                                                             34
Nested Intervals
Rational Number Encodings




                            35
Nested Intervals Model

  Rational numbers (a/b, with a and b integers)


   ((p.lft <= c.lft) AND (c.rgt <= p.rgt))



                 0/5         A          5/5




  1/5       B          2/5        3/5         C   4/5


                                                        36
Nested Intervals Model




   a                     b




                             37
Nested Intervals Model




   a                                  b

            a+(b-a)/3    a+2(b-a)/3




                                          37
Nested Intervals Model

  Finding GCD (greatest common divisor)

  CREATE FUNCTION gcd(IN x INTEGER, IN y INTEGER)
  RETURNS INTEGER
  LANGUAGE SQL DETERMINISTIC
  BEGIN

  WHILE x <> y DO
     IF x > y THEN SET x = x - y; END IF;
     IF y > x THEN SET y = y - x; END IF;
  END WHILE;
  RETURN x;

  END;



                                                    38
Nested Intervals Model

  Binary                 Node (x, y)
 Fractions




                                   39
Nested Intervals Model

  Binary                           Node (x, y)
 Fractions



                         First node (1, 1/2)




                                               39
Nested Intervals Model

  Binary                           Node (x, y)
 Fractions



                         First node (1, 1/2)



                                   depth-first
                            convergence point




                                               39
Nested Intervals Model

  Binary                           Node (x, y)
 Fractions
                          First child of first node (1, 3/4)




                         First node (1, 1/2)



                                   depth-first
                            convergence point




                                                       39
Nested Intervals Model

  Binary                           Node (x, y)
 Fractions
                          First child of first node (1, 3/4)




                         First node (1, 1/2)



                                   depth-first
                            convergence point

                                 breadth-first
                            convergence point
                                                       39
Nested Intervals Model

  Binary                           Node (x, y)
 Fractions
                          First child of first node (1, 3/4)




                         First node (1, 1/2)



                                   depth-first
                            convergence point

                                 breadth-first
                            convergence point
                                                       39
Nested Intervals Model

  Binary                           Node (x, y)
 Fractions
                          First child of first node (1, 3/4)




                         First node (1, 1/2)



                                   depth-first
                            convergence point

                                 breadth-first
                            convergence point
                                                       39
Nested Intervals Model




                         40
Nested Intervals Model
                    CREATE FUNCTION x_numer(
                     IN numer INT, IN denom INT
                    ) RETURNS INTEGER
                    BEGIN

                     DECLARE ret_num INTEGER;
                     DECLARE ret_den INTEGER;
                     SET ret_num = numer + 1;
                     SET ret_den = 2 * denom;
                     WHILE FLOOR(ret_num/2)
                           = ret_num/2
                     DO SET ret_num = ret_num/2;
                        SET red_den = ret_den/2;
                     END WHILE;
                     RETURN ret_num;   -- ret_den
                                 -- for x_denom()
                    END;
                                                  40
Nested Intervals Model
CREATE FUNCTION parent_numer(IN numer INTEGER,
IN denom INTEGER) RETURNS INTEGER
LANGUAGE SQL DETERMINISTIC
BEGIN
 DECLARE ret_num INTEGER;
 DECLARE ret_den INTEGER;
 IF numer = 3
    THEN RETURN CAST(NULL AS INTEGER)
 END IF;
 SET ret_num = (numer - 1)/2;
 SET ret_den = denom/2;
 WHILE FLOOR((ret_num - 1)/4) = (ret_num - 1)/4
 DO SET ret_num = (ret_num + 1)/2;
    SET red_den = ret_den/2;
 END WHILE;
 RETURN ret_num; -- ret_den for parent_denom()
END;
                                                  41
Nested Intervals Model

Similar functions for:
  sibling_numer(), sibling_denom()
  child_numer(), child_denom()
  enumerated_path(), distance()
  path_numer(), path_denom()




                                     42
Nested Intervals Model

Similar functions for:
  sibling_numer(), sibling_denom()
  child_numer(), child_denom()
  enumerated_path(), distance()
  path_numer(), path_denom()


INSERT INTO   orgchart (name, numer, denom) VALUES
(‘Anthony’,   path_numer(‘1’),   path_denom(‘1’)),
(‘Beryl’,     path_numer(‘1.1’), path_denom(‘1.1’)),
(‘Charles’,   path_numer(‘1.2’), path_denom(‘1.2’)),
(‘Denise’,    path_numer(‘1.2.1’), path_denom(‘1.2.1’));



                                                      42
Nested Intervals Encodings

  Interval Halving


    average:
    (lft + rgt) / 2




                             43
Nested Intervals Encodings

  Interval Halving


    average:
    (lft + rgt) / 2



  Farey Fractions
  a/b and c/d neighbours
  => bc -ad = 1


   mediant:
   (lft_num + rgt_num)
   (lft_den + rgt_den)


                             43
Nested Intervals Encodings

  Continued Fractions



                                          1.1.2.1


  Reverse (or additive) Continued Fractions




                                                    44
Proprietary Solutions
Oracle




                        45
Oracle: CONNECT BY PRIOR

  Traversing the tree
      SELECT   emp, boss
        FROM   emp_orgchart
       START   WITH boss IS NULL
  CONNECT BY   [NOCYCLE] PRIOR emp = boss;


                        emp     boss
                         A      NULL
                         B       A
                         G       B
                         C       A
                         D       C
                         E       C
                         F       C

                                             46
Oracle: CONNECT BY PRIOR

  Traversing the tree
      SELECT   emp, boss
        FROM   emp_orgchart
       START   WITH boss = ‘C’
                         IS NULL
  CONNECT BY   [NOCYCLE] PRIOR emp = boss;




                        emp     boss
                        D        C
                         E       C
                         F       C



                                             46
Oracle: CONNECT BY PRIOR
  Traversing the tree
         SELECT emp, boss, salary, LEVEL AS lvl,
                   LPAD(' ', 2*(LEVEL-1)) || emp AS tree,
                   CONNECT_BY_IS_LEAF AS is_leaf
            FROM emp_orgchart
   CONNECT BY PRIOR emp = boss
           START WITH boss IS NULL
  ORDER SIBLINGS BY salary DESC;
     emp    boss    salary    lvl       tree    is_leaf
      A     NULL    1000.00    1    A              0
      B      A       900.00    2        B          0
      G      B       800.00    3            G      1
      C      A       900.00    2        C          0
      D      C       800.00    3            D      1
      E      C       700.00    3            E      1
      F      C       600.00    3            F      1
                                                          47
Oracle: CONNECT BY PRIOR

  Determining the relationship between two nodes

   SELECT COUNT(*) AS ‘is_subordinate’
     FROM emp_orgchart
    WHERE emp = :subordinate
      AND LEVEL > 1
    START WITH emp = :superior
  CONNECT BY PRIOR emp = boss;




                                                   48
Oracle: CONNECT BY PRIOR

  Determining the relationship between two nodes

   SELECT COUNT(*) AS ‘is_subordinate’
     FROM emp_orgchart
    WHERE emp = :subordinate
      AND LEVEL > 1
    START WITH emp = :superior
  CONNECT BY PRIOR emp = boss;



                  A subordinate of C? 0
                  F subordinate of A? 1


                                                   48
Oracle: CONNECT_BY_ROOT

 Determining the ancestor of a node

      SELECT emp_id,
             CONNECT_BY_ROOT emp_id AS root
        FROM orgchart
  START WITH boss = ‘A’
  CONNECT BY PRIOR emp_id = boss;


                  emp_id          root
                    B               B
                    G               B
                    C              C
                    D              C
                    E              C
                    F              C

                                              49
Oracle: SYS_CONNECT_BY_PATH

 Materialized Path View
      SELECT emp_id,
             SYS_CONNECT_BY_PATH (emp_id,'.')
             AS path_string
        FROM orgchart
  START WITH boss IS NULL
  CONNECT BY PRIOR emp_id = boss
    ORDER BY 2;
                          emp_id     path_string
                   A               .A
                   B               .A.B
                   C               .A.C
                   D               .A.C.D
                   E               .A.C.E
                   F               .A.C.F

                                                   50
Common Table Expressions
SQL-99 Standard




                           51
Common Table Expressions
CREATE TABLE emp_orgchart (
  emp VARCHAR(10) PRIMARY KEY,
  boss VARCHAR(10) REFERENCES emp_orgchart(emp_id),
  salary TEXT
);

INSERT   INTO emp_orgchart (emp, boss, salary) VALUES
 (‘A’,   NULL, 1000.00),
 (‘B’,   ‘A’, 900.00),
 (‘C’,   ‘A’, 900.00),               A
 (‘D’,   ‘C’, 800.00),
 (‘E’,   ‘C’, 700.00),
 (‘F’,   ‘C’, 600.00),        B            C
 (‘G’,   ‘B’, 800.00);

                          G        D       E      F

                                                        52
Common Table Expressions

WITH RECURSIVE hierarchy AS (
  -- non recursive term
  SELECT *
    FROM emp_orgchart
   WHERE boss IS NULL
  UNION ALL
  -- recursive term
  SELECT E1.*
    FROM emp_orgchart AS E1
    JOIN hierarchy AS E2
      ON E1.boss = E2.emp
)
  SELECT *
    FROM hierarchy
ORDER BY emp;


                                53
Common Table Expressions

WITH RECURSIVE hierarchy AS (
  -- non recursive term
  SELECT *
    FROM emp_orgchart
   WHERE boss IS NULL
  UNION ALL
  -- recursive term
  SELECT E1.*
    FROM emp_orgchart AS E1
    JOIN hierarchy AS E2
      ON E1.boss = E2.emp
)
  SELECT *
    FROM hierarchy
ORDER BY emp;


                                53
Common Table Expressions

WITH RECURSIVE hierarchy AS (
  -- non recursive term
  SELECT *
    FROM emp_orgchart
   WHERE boss IS NULL
  UNION ALL
  -- recursive term
  SELECT E1.*
    FROM emp_orgchart AS E1
    JOIN hierarchy AS E2
      ON E1.boss = E2.emp
)
  SELECT *
    FROM hierarchy
ORDER BY emp;


                                53
Common Table Expressions

WITH RECURSIVE hierarchy AS (
  -- non recursive term
  SELECT *
    FROM emp_orgchart
   WHERE boss IS NULL           emp   boss   salary
  UNION ALL                      A    NULL   1000.00
  -- recursive term              B     A      900.00
  SELECT E1.*                    C     A      900.00
    FROM emp_orgchart AS E1      D     C      800.00
    JOIN hierarchy AS E2
                                 E     C      700.00
      ON E1.boss = E2.emp
                                 F     C      600.00
)
  SELECT *                       G     B      800.00
    FROM hierarchy
ORDER BY emp;


                                                       53
Common Table Expressions
WITH RECURSIVE hierarchy AS (
  SELECT *,
         1 AS lvl,
         CAST(emp AS TEXT) AS tree,
         emp || ‘.’ AS path
    FROM emp_orgchart
   WHERE boss IS NULL
  UNION ALL
  SELECT E1.*,
         E2.lvl + 1 AS lvl,
         LPAD(E1.emp, lvl * 2, ‘ ’) AS tree,
         E2.path || E1.emp || ‘.’ AS path
    FROM emp_orgchart
    JOIN hierarchy AS E2
      ON E1.boss = E2.emp
)
  SELECT *
    FROM hierarchy
ORDER BY path;
                                               54
Common Table Expressions
WITH RECURSIVE hierarchy AS (
  SELECT *,
         1 AS lvl,
         CAST(emp AS TEXT) AS tree,
         emp || ‘.’ AS path
    FROM emp_orgchart
   WHERE boss IS NULL
  UNION ALL
  SELECT E1.*,
         E2.lvl + 1 AS lvl,
         LPAD(E1.emp, lvl * 2, ‘ ’) AS tree,
         E2.path || E1.emp || ‘.’ AS path
    FROM emp_orgchart
    JOIN hierarchy AS E2
      ON E1.boss = E2.emp
)
  SELECT *
    FROM hierarchy
ORDER BY path;
                                               54
Common Table Expressions
WITH RECURSIVE hierarchy AS (
  SELECT *,
         1 AS lvl,
         CAST(emp AS TEXT) AS tree,
         emp || ‘.’ AS path
    FROM emp_orgchart
   WHERE boss IS NULL
  UNION ALL
  SELECT E1.*,
         E2.lvl + 1 AS lvl,
         LPAD(E1.emp, lvl * 2, ‘ ’) AS tree,
         E2.path || E1.emp || ‘.’ AS path
    FROM emp_orgchart
    JOIN hierarchy AS E2
      ON E1.boss = E2.emp
)
  SELECT *
    FROM hierarchy
ORDER BY path;
                                               54
Common Table Expressions
WITH RECURSIVE hierarchy AS (
  SELECT *,
         1 AS lvl,
         CAST(emp AS TEXT) AS tree,
         emp || ‘.’ AS path
    FROM emp_orgchart
   WHERE boss IS NULL
  UNION ALL
  SELECT E1.*,
         E2.lvl + 1 AS lvl,
         LPAD(E1.emp, lvl * 2, ‘ ’) AS tree,
         E2.path || E1.emp || ‘.’ AS path
    FROM emp_orgchart
    JOIN hierarchy AS E2
      ON E1.boss = E2.emp
)
  SELECT *
    FROM hierarchy
ORDER BY path;
                                               54
Common Table Expressions
WITH RECURSIVE hierarchy AS (
  SELECT *,
         1 AS lvl,
         CAST(emp AS TEXT) AS tree,
         emp || ‘.’ AS path
    FROM emp_orgchart
   WHERE boss IS NULL
  UNION ALL
  SELECT E1.*,
         E2.lvl + 1 AS lvl,
         LPAD(E1.emp, lvl * 2, ‘ ’) AS tree,
         E2.path || E1.emp || ‘.’ AS path
    FROM emp_orgchart
    JOIN hierarchy AS E2
      ON E1.boss = E2.emp
)
  SELECT *
    FROM hierarchy
ORDER BY path;
                                               54
Common Table Expressions
WITH RECURSIVE hierarchy AS (
  SELECT *,
         1 AS lvl,
  emp    CAST(emp salary
         boss     AS TEXT) AS tree, tree
                            lvl                 path
         emp || ‘.’ AS path
   A     NULL     1000.00    1   A         A.
    FROM emp_orgchart
   WHERE boss IS NULL
   B       A       900.00    2     B       A.B.
  UNION ALL
  SELECT E1.*,
   G       B       800.00    3        G    A.B.G.
         E2.lvl + 1 AS lvl,
   C     LPAD(E1.emp, lvl * 2, ‘ ’)CAS tree,
           A       900.00    2             A.C.
         E2.path || E1.emp || ‘.’ AS path
   D       C       800.00
    FROM emp_orgchart        3        D    A.C.D.
    JOIN hierarchy AS E2
   E       C       700.00    3        E    A.C.E.
      ON E1.boss = E2.emp
) F        C       600.00    3        F    A.C.F.
  SELECT *
    FROM hierarchy
ORDER BY path;
                                                       54
Common Table Expressions

WITH RECURSIVE hierarchy AS (
  SELECT *,
         1 AS lvl,
         CAST(emp AS TEXT) AS tree
    FROM emp_orgchart
   WHERE boss = ‘A’
  UNION ALL
  SELECT E1.*,
         E2.lvl + 1 AS lvl,
         LPAD(E1.emp, depth * 2, ‘ ’) AS tree
    FROM emp_orgchart
    JOIN hierarchy AS E2 ON E1.boss = E2.emp
   WHERE E2.lvl < 3 -- termination condition
)
  SELECT *
    FROM hierarchy
ORDER BY path;

                                                55
Common Table Expressions
WITH RECURSIVE hierarchy AS (
  SELECT *,
         1 AS lvl,
         CAST(emp AS TEXT) AS tree
    FROM emp_orgchart
   WHERE boss = ‘A’
  UNION ALL
  SELECT E1.*,
         E2.lvl + 1 AS lvl,
         LPAD(E1.emp, depth * 2, ‘ ’) AS tree
    FROM emp_orgchart
    JOIN hierarchy AS E2 ON E1.boss = E2.emp
)
SELECT *,
       COALESCE((SELECT 0 FROM emp_orgchart E3
                  WHERE hierarchy.emp = E3.boss
                  FETCH FIRST ROW ONLY), 1) AS is_leaf
    FROM hierarchy;

                                                         56
And the winner is...




                       57
And the winner is...




                       57
Questions ?




              58
Resources
Joe Celko, “Trees and Hierarchies in SQL for
Smarties”, Morgan Kaufmann:
http://www.amazon.com/dp/1558609202/



Vadim Tropashko, various articles and papers:

http://www.dbazine.com/top-auth/top-auth-trop/
http://www.sigmod.org/sigmod/record/issues/
0506/p47-article-tropashko.pdf
http://arxiv.org/pdf/cs/0402051



                                                 59
Thank you!
            Contact details:

    Lorenzo Alberton
     lorenzo@ibuildings.com
    http://www.alberton.info
http://joind.in/talk/view/585

More Related Content

What's hot

アドテクに携わって培った アプリをハイパフォーマンスに保つ設計とコーディング
アドテクに携わって培った アプリをハイパフォーマンスに保つ設計とコーディング アドテクに携わって培った アプリをハイパフォーマンスに保つ設計とコーディング
アドテクに携わって培った アプリをハイパフォーマンスに保つ設計とコーディング MicroAd, Inc.(Engineer)
 
Etsy Activity Feeds Architecture
Etsy Activity Feeds ArchitectureEtsy Activity Feeds Architecture
Etsy Activity Feeds ArchitectureDan McKinley
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and EffectsMartin Odersky
 
Boost Performance With My S Q L 51 Partitions
Boost Performance With  My S Q L 51 PartitionsBoost Performance With  My S Q L 51 Partitions
Boost Performance With My S Q L 51 PartitionsPerconaPerformance
 
HandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLHandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLakirahiguchi
 
Modern Algorithms and Data Structures - 1. Bloom Filters, Merkle Trees
Modern Algorithms and Data Structures - 1. Bloom Filters, Merkle TreesModern Algorithms and Data Structures - 1. Bloom Filters, Merkle Trees
Modern Algorithms and Data Structures - 1. Bloom Filters, Merkle TreesLorenzo Alberton
 
The art of readable code ( pdf )
The art of readable code ( pdf )The art of readable code ( pdf )
The art of readable code ( pdf )Jocelyn Hsu
 
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)Satoshi Yamada
 
Neo4j Training Cypher
Neo4j Training CypherNeo4j Training Cypher
Neo4j Training CypherMax De Marzi
 
Almost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and OrchestratorAlmost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and OrchestratorJean-François Gagné
 
Using Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query PerformanceUsing Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query Performanceoysteing
 
Exception handling
Exception handlingException handling
Exception handlingIblesoft
 
Neo4j Introduction (Basics, Cypher, RDBMS to GRAPH)
Neo4j Introduction (Basics, Cypher, RDBMS to GRAPH) Neo4j Introduction (Basics, Cypher, RDBMS to GRAPH)
Neo4j Introduction (Basics, Cypher, RDBMS to GRAPH) David Fombella Pombal
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Scott Wlaschin
 
Best Practices in Security with PostgreSQL
Best Practices in Security with PostgreSQLBest Practices in Security with PostgreSQL
Best Practices in Security with PostgreSQLEDB
 
Top 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark ApplicationsTop 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark ApplicationsSpark Summit
 
Dataflow shuffle service
Dataflow shuffle service Dataflow shuffle service
Dataflow shuffle service Yuta Hono
 

What's hot (20)

アドテクに携わって培った アプリをハイパフォーマンスに保つ設計とコーディング
アドテクに携わって培った アプリをハイパフォーマンスに保つ設計とコーディング アドテクに携わって培った アプリをハイパフォーマンスに保つ設計とコーディング
アドテクに携わって培った アプリをハイパフォーマンスに保つ設計とコーディング
 
Etsy Activity Feeds Architecture
Etsy Activity Feeds ArchitectureEtsy Activity Feeds Architecture
Etsy Activity Feeds Architecture
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
Boost Performance With My S Q L 51 Partitions
Boost Performance With  My S Q L 51 PartitionsBoost Performance With  My S Q L 51 Partitions
Boost Performance With My S Q L 51 Partitions
 
HandlerSocket plugin for MySQL
HandlerSocket plugin for MySQLHandlerSocket plugin for MySQL
HandlerSocket plugin for MySQL
 
Cpp reference card
Cpp reference cardCpp reference card
Cpp reference card
 
Programmation Fonctionnelle
Programmation FonctionnelleProgrammation Fonctionnelle
Programmation Fonctionnelle
 
MySQL Tuning
MySQL TuningMySQL Tuning
MySQL Tuning
 
Modern Algorithms and Data Structures - 1. Bloom Filters, Merkle Trees
Modern Algorithms and Data Structures - 1. Bloom Filters, Merkle TreesModern Algorithms and Data Structures - 1. Bloom Filters, Merkle Trees
Modern Algorithms and Data Structures - 1. Bloom Filters, Merkle Trees
 
The art of readable code ( pdf )
The art of readable code ( pdf )The art of readable code ( pdf )
The art of readable code ( pdf )
 
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
PostgreSQLの実行計画を読み解こう(OSC2015 Spring/Tokyo)
 
Neo4j Training Cypher
Neo4j Training CypherNeo4j Training Cypher
Neo4j Training Cypher
 
Almost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and OrchestratorAlmost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
Almost Perfect Service Discovery and Failover with ProxySQL and Orchestrator
 
Using Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query PerformanceUsing Optimizer Hints to Improve MySQL Query Performance
Using Optimizer Hints to Improve MySQL Query Performance
 
Exception handling
Exception handlingException handling
Exception handling
 
Neo4j Introduction (Basics, Cypher, RDBMS to GRAPH)
Neo4j Introduction (Basics, Cypher, RDBMS to GRAPH) Neo4j Introduction (Basics, Cypher, RDBMS to GRAPH)
Neo4j Introduction (Basics, Cypher, RDBMS to GRAPH)
 
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014Domain Driven Design with the F# type System -- F#unctional Londoners 2014
Domain Driven Design with the F# type System -- F#unctional Londoners 2014
 
Best Practices in Security with PostgreSQL
Best Practices in Security with PostgreSQLBest Practices in Security with PostgreSQL
Best Practices in Security with PostgreSQL
 
Top 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark ApplicationsTop 5 Mistakes When Writing Spark Applications
Top 5 Mistakes When Writing Spark Applications
 
Dataflow shuffle service
Dataflow shuffle service Dataflow shuffle service
Dataflow shuffle service
 

Viewers also liked

Network Intent Composition in OpenDaylight
Network Intent Composition in OpenDaylightNetwork Intent Composition in OpenDaylight
Network Intent Composition in OpenDaylightOpenDaylight
 
Hadoop-DS: Which SQL-on-Hadoop Rules the Herd
Hadoop-DS: Which SQL-on-Hadoop Rules the HerdHadoop-DS: Which SQL-on-Hadoop Rules the Herd
Hadoop-DS: Which SQL-on-Hadoop Rules the HerdIBM Analytics
 
HBaseCon2017 Transactions in HBase
HBaseCon2017 Transactions in HBaseHBaseCon2017 Transactions in HBase
HBaseCon2017 Transactions in HBaseHBaseCon
 
Scaling Teams, Processes and Architectures
Scaling Teams, Processes and ArchitecturesScaling Teams, Processes and Architectures
Scaling Teams, Processes and ArchitecturesLorenzo Alberton
 
The Art of Scalability - Managing growth
The Art of Scalability - Managing growthThe Art of Scalability - Managing growth
The Art of Scalability - Managing growthLorenzo Alberton
 
Monitoring at scale - Intuitive dashboard design
Monitoring at scale - Intuitive dashboard designMonitoring at scale - Intuitive dashboard design
Monitoring at scale - Intuitive dashboard designLorenzo Alberton
 
NoSQL Databases: Why, what and when
NoSQL Databases: Why, what and whenNoSQL Databases: Why, what and when
NoSQL Databases: Why, what and whenLorenzo Alberton
 
MySQL Group Replication
MySQL Group ReplicationMySQL Group Replication
MySQL Group ReplicationKenny Gryp
 
Inno db internals innodb file formats and source code structure
Inno db internals innodb file formats and source code structureInno db internals innodb file formats and source code structure
Inno db internals innodb file formats and source code structurezhaolinjnu
 
MySQL InnoDB Cluster - Group Replication
MySQL InnoDB Cluster - Group ReplicationMySQL InnoDB Cluster - Group Replication
MySQL InnoDB Cluster - Group ReplicationFrederic Descamps
 
Percona XtraDB Cluster vs Galera Cluster vs MySQL Group Replication
Percona XtraDB Cluster vs Galera Cluster vs MySQL Group ReplicationPercona XtraDB Cluster vs Galera Cluster vs MySQL Group Replication
Percona XtraDB Cluster vs Galera Cluster vs MySQL Group ReplicationKenny Gryp
 
MySQL Best Practices - OTN LAD Tour
MySQL Best Practices - OTN LAD TourMySQL Best Practices - OTN LAD Tour
MySQL Best Practices - OTN LAD TourRonald Bradford
 
MySQL 5.7: Focus on InnoDB
MySQL 5.7: Focus on InnoDBMySQL 5.7: Focus on InnoDB
MySQL 5.7: Focus on InnoDBMario Beck
 
Mysql参数-GDB
Mysql参数-GDBMysql参数-GDB
Mysql参数-GDBzhaolinjnu
 
MySQL Group Replication
MySQL Group ReplicationMySQL Group Replication
MySQL Group ReplicationManish Kumar
 
Using Apache Spark and MySQL for Data Analysis
Using Apache Spark and MySQL for Data AnalysisUsing Apache Spark and MySQL for Data Analysis
Using Apache Spark and MySQL for Data AnalysisSveta Smirnova
 
MySQL High-Availability and Scale-Out architectures
MySQL High-Availability and Scale-Out architecturesMySQL High-Availability and Scale-Out architectures
MySQL High-Availability and Scale-Out architecturesFromDual GmbH
 
MySQL InnoDB Cluster and MySQL Group Replication @HKOSC 2017
MySQL InnoDB Cluster and MySQL Group Replication @HKOSC 2017MySQL InnoDB Cluster and MySQL Group Replication @HKOSC 2017
MySQL InnoDB Cluster and MySQL Group Replication @HKOSC 2017Ivan Ma
 
Multi Source Replication With MySQL 5.7 @ Verisure
Multi Source Replication With MySQL 5.7 @ VerisureMulti Source Replication With MySQL 5.7 @ Verisure
Multi Source Replication With MySQL 5.7 @ VerisureKenny Gryp
 

Viewers also liked (20)

Network Intent Composition in OpenDaylight
Network Intent Composition in OpenDaylightNetwork Intent Composition in OpenDaylight
Network Intent Composition in OpenDaylight
 
Hadoop-DS: Which SQL-on-Hadoop Rules the Herd
Hadoop-DS: Which SQL-on-Hadoop Rules the HerdHadoop-DS: Which SQL-on-Hadoop Rules the Herd
Hadoop-DS: Which SQL-on-Hadoop Rules the Herd
 
HBaseCon2017 Transactions in HBase
HBaseCon2017 Transactions in HBaseHBaseCon2017 Transactions in HBase
HBaseCon2017 Transactions in HBase
 
Scaling Teams, Processes and Architectures
Scaling Teams, Processes and ArchitecturesScaling Teams, Processes and Architectures
Scaling Teams, Processes and Architectures
 
The Art of Scalability - Managing growth
The Art of Scalability - Managing growthThe Art of Scalability - Managing growth
The Art of Scalability - Managing growth
 
Monitoring at scale - Intuitive dashboard design
Monitoring at scale - Intuitive dashboard designMonitoring at scale - Intuitive dashboard design
Monitoring at scale - Intuitive dashboard design
 
NoSQL Databases: Why, what and when
NoSQL Databases: Why, what and whenNoSQL Databases: Why, what and when
NoSQL Databases: Why, what and when
 
Models for hierarchical data
Models for hierarchical dataModels for hierarchical data
Models for hierarchical data
 
MySQL Group Replication
MySQL Group ReplicationMySQL Group Replication
MySQL Group Replication
 
Inno db internals innodb file formats and source code structure
Inno db internals innodb file formats and source code structureInno db internals innodb file formats and source code structure
Inno db internals innodb file formats and source code structure
 
MySQL InnoDB Cluster - Group Replication
MySQL InnoDB Cluster - Group ReplicationMySQL InnoDB Cluster - Group Replication
MySQL InnoDB Cluster - Group Replication
 
Percona XtraDB Cluster vs Galera Cluster vs MySQL Group Replication
Percona XtraDB Cluster vs Galera Cluster vs MySQL Group ReplicationPercona XtraDB Cluster vs Galera Cluster vs MySQL Group Replication
Percona XtraDB Cluster vs Galera Cluster vs MySQL Group Replication
 
MySQL Best Practices - OTN LAD Tour
MySQL Best Practices - OTN LAD TourMySQL Best Practices - OTN LAD Tour
MySQL Best Practices - OTN LAD Tour
 
MySQL 5.7: Focus on InnoDB
MySQL 5.7: Focus on InnoDBMySQL 5.7: Focus on InnoDB
MySQL 5.7: Focus on InnoDB
 
Mysql参数-GDB
Mysql参数-GDBMysql参数-GDB
Mysql参数-GDB
 
MySQL Group Replication
MySQL Group ReplicationMySQL Group Replication
MySQL Group Replication
 
Using Apache Spark and MySQL for Data Analysis
Using Apache Spark and MySQL for Data AnalysisUsing Apache Spark and MySQL for Data Analysis
Using Apache Spark and MySQL for Data Analysis
 
MySQL High-Availability and Scale-Out architectures
MySQL High-Availability and Scale-Out architecturesMySQL High-Availability and Scale-Out architectures
MySQL High-Availability and Scale-Out architectures
 
MySQL InnoDB Cluster and MySQL Group Replication @HKOSC 2017
MySQL InnoDB Cluster and MySQL Group Replication @HKOSC 2017MySQL InnoDB Cluster and MySQL Group Replication @HKOSC 2017
MySQL InnoDB Cluster and MySQL Group Replication @HKOSC 2017
 
Multi Source Replication With MySQL 5.7 @ Verisure
Multi Source Replication With MySQL 5.7 @ VerisureMulti Source Replication With MySQL 5.7 @ Verisure
Multi Source Replication With MySQL 5.7 @ Verisure
 

Recently uploaded

All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFMichael Gough
 
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...itnewsafrica
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Jeffrey Haguewood
 
Kuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialKuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialJoão Esperancinha
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Hiroshi SHIBATA
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfAarwolf Industries LLC
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integrationmarketing932765
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...Wes McKinney
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentMahmoud Rabie
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observabilityitnewsafrica
 

Recently uploaded (20)

All These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDFAll These Sophisticated Attacks, Can We Really Detect Them - PDF
All These Sophisticated Attacks, Can We Really Detect Them - PDF
 
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
Irene Moetsana-Moeng: Stakeholders in Cybersecurity: Collaborative Defence fo...
 
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
Email Marketing Automation for Bonterra Impact Management (fka Social Solutio...
 
Kuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorialKuma Meshes Part I - The basics - A tutorial
Kuma Meshes Part I - The basics - A tutorial
 
Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024Long journey of Ruby standard library at RubyConf AU 2024
Long journey of Ruby standard library at RubyConf AU 2024
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdf
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS:  6 Ways to Automate Your Data IntegrationBridging Between CAD & GIS:  6 Ways to Automate Your Data Integration
Bridging Between CAD & GIS: 6 Ways to Automate Your Data Integration
 
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
The Future Roadmap for the Composable Data Stack - Wes McKinney - Data Counci...
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Digital Tools & AI in Career Development
Digital Tools & AI in Career DevelopmentDigital Tools & AI in Career Development
Digital Tools & AI in Career Development
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security ObservabilityGlenn Lazarus- Why Your Observability Strategy Needs Security Observability
Glenn Lazarus- Why Your Observability Strategy Needs Security Observability
 

Trees In The Database - Advanced data structures

  • 1. Trees in the Database Advanced Data Structures Lorenzo Alberton lorenzo@ibuildings.com DPC09, Amsterdam, 13 June 2009
  • 3. Lorenzo Alberton MDB2 Calendar Pager Translation2 Mail_Queue DB_QueryTool 2
  • 4. Lorenzo Alberton MDB2 Calendar Pager Translation2 Mail_Queue DB_QueryTool 2
  • 5. Tree Connected, undirected, acyclic graph A B C G D E F 3
  • 10. Adjacency List Model AKA “parent-child” model 4
  • 11. Adjacency List Model CREATE TABLE emp_orgchart ( emp VARCHAR(10) NOT NULL PRIMARY KEY, boss VARCHAR(10), salary DECIMAL(6,2) NOT NULL ); A emp boss salary A NULL 1000.00 B C B A 900.00 C A 900.00 D C 800.00 D E F E C 700.00 F C 600.00 5
  • 12. Adjacency List Model Finding the root node SELECT * FROM emp_orgchart WHERE boss IS NULL; Finding the leaf nodes SELECT e1.* FROM emp_orgchart AS e1 LEFT JOIN emp_orgchart AS e2 ON e1.emp = e2.boss WHERE e2.emp IS NULL; 6
  • 13. Adjacency List Model Anomalies UPDATE anomalies START TRANSACTION; emp boss salary UPDATE emp_orgchart A NULL 1000.00 SET emp = ‘C1’ B A 900.00 WHERE emp = ‘C’; C1 A 900.00 D C 800.00 UPDATE emp_orgchart E C 700.00 SET boss = ‘C1’ F C 600.00 WHERE boss = ‘C’; COMMIT; 7
  • 14. Adjacency List Model Anomalies UPDATE anomalies START TRANSACTION; emp boss salary UPDATE emp_orgchart A NULL 1000.00 SET emp = ‘C1’ B A 900.00 WHERE emp = ‘C’; C1 A 900.00 D C 800.00 UPDATE emp_orgchart E C 700.00 SET boss = ‘C1’ F C 600.00 WHERE boss = ‘C’; COMMIT; 7
  • 15. Adjacency List Model Anomalies UPDATE anomalies START TRANSACTION; UPDATE emp_orgchart SET emp = CASE emp UPDATE emp_orgchart WHEN ‘C’ THEN ‘C1’ SET emp = ‘C1’ ELSE emp END, WHERE emp = ‘C’; boss = CASE boss WHEN ‘C’ THEN ‘C1’ UPDATE emp_orgchart ELSE boss END SET boss = ‘C1’ WHERE ‘C’ IN (emp, boss); WHERE boss = ‘C’; COMMIT; 7
  • 16. Adjacency List Model Anomalies INSERT anomalies 8
  • 17. Adjacency List Model Anomalies INSERT anomalies INSERT INTO emp_orgchart (emp, boss) VALUES (‘G’, ‘H’), (‘H’, ‘G’); G H 8
  • 18. Adjacency List Model Anomalies INSERT anomalies INSERT INTO emp_orgchart (emp, boss) VALUES (‘G’, ‘H’), (‘H’, ‘G’); G H INSERT INTO emp_orgchart VALUES (‘M’, ‘M’); M 8
  • 19. Adjacency List Model Anomalies DELETE anomalies DELETE FROM emp_orgchart WHERE emp = ‘C’; A B C D E F 9
  • 20. Adjacency List Model Anomalies DELETE anomalies DELETE FROM emp_orgchart WHERE emp = ‘C’; A B C D E F 9
  • 21. Fixing the Adjacency List Model CREATE TABLE emp ( id INTEGER DEFAULT 0 PRIMARY KEY, name VARCHAR(10) NOT NULL, salary DECIMAL (6,2) NOT NULL CHECK (salary >= 0.00), ... ); CREATE TABLE orgchart ( emp_id INTEGER NOT NULL DEFAULT 0 -- vacant REFERENCES emp(id) ON DELETE SET DEFAULT ON UPDATE CASCADE, boss_id INTEGER -- NULL means root node REFERENCES emp(id), ... ); 10
  • 22. Fixing the Adjacency List Model -- cannot be your own boss CHECK ((boss_id <> emp_id) OR (boss_id = 0 AND emp_id = 0)), 11
  • 23. Fixing the Adjacency List Model -- cannot be your own boss CHECK ((boss_id <> emp_id) OR (boss_id = 0 AND emp_id = 0)), -- prevent longer cycles UNIQUE (emp_id, boss_id), 11
  • 24. Fixing the Adjacency List Model -- cannot be your own boss CHECK ((boss_id <> emp_id) OR (boss_id = 0 AND emp_id = 0)), -- prevent longer cycles UNIQUE (emp_id, boss_id), -- connected graph (edges = nodes - 1) CHECK ((SELECT COUNT(*) FROM orgchart) - 1 = (SELECT COUNT(boss_id) FROM orgchart)), 11
  • 25. Fixing the Adjacency List Model -- cannot be your own boss CHECK ((boss_id <> emp_id) OR (boss_id = 0 AND emp_id = 0)), -- prevent longer cycles UNIQUE (emp_id, boss_id), -- connected graph (edges = nodes - 1) CHECK ((SELECT COUNT(*) FROM orgchart) - 1 = (SELECT COUNT(boss_id) FROM orgchart)), -- one root only CHECK ((SELECT COUNT(*) FROM orgchart WHERE boss_id IS NULL) = 1), 11
  • 26. Adjacency List Model - Navigation Loops / Self-Joins procedural code SELECT o1.emp AS e1, o2.emp AS e2, CREATE PROCEDURE o3.emp AS e3 TreeTraversal (IN FROM emp_orgchart AS o1 current_emp_id INT) LEFT OUTER JOIN BEGIN emp_orgchart AS o2 ... ON o1.emp = o2.boss LEFT OUTER JOIN emp_orgchart AS o3 ON o2.emp = o3.boss WHERE o1.emp = ‘A’; 12
  • 27. Adjacency List Model - Deletion 13
  • 28. Adjacency List Model - Deletion A B C D E F 13
  • 29. Adjacency List Model - Deletion A B C D x E F 13
  • 30. Adjacency List Model - Deletion A A B C B C D x E F D E F 13
  • 31. Adjacency List Model - Deletion A A A B C B C D x E F B D D E E F F 13
  • 32. Adjacency List Model - Deletion A A A A B C B C B C D x E F B D D E E F F D E F 13
  • 33. Adjacency List Model - Deletion A A A A B C B C B D C D x E F B D D E E F F D E F 13
  • 34. Adjacency List Model - Deletion A A A A B C B C B D C D x E F B D D E E F F D E F Requires traversal (deferred constraints) 13
  • 35. Path Enumeration Model aka Materialized Path 14
  • 36. Path Enumeration Model CREATE TABLE emp_orgchart ( emp_id CHAR(1) NOT NULL PRIMARY KEY -- if using a separator, don’t use it in the ID CHECK (REPLACE(emp_id, ‘/’, ‘’) = emp_id), emp_name VARCHAR(10) NOT NULL, path_string VARCHAR(512) NOT NULL ); emp_id emp_name path_string A A Anthony A B Beryl AB B C C Charles AC D Denise ACD E Ellen ACE D E F F Frank ACF 15
  • 37. Path Enumeration Model -- prevent cycles (nodes appearing twice: ‘ABCA’) CHECK (NOT EXISTS( SELECT * FROM emp_orgchart AS D1, emp_orgchart AS P1 WHERE LENGTH(REPLACE(P1.path_string, D1.emp_id, ‘’)) < LENGTH(P1.path_string) - LENGTH(D1.emp_id)) )) -- No path can be longer than the number of nodes CHECK((SELECT MAX(LENGTH(path_string)) FROM emp_orgchart AS E1) <= (SELECT COUNT(emp_id) * LENGTH(emp_id) FROM emp_orgchart AS E2)) 16
  • 39. Path Enumeration Model Depth of the node 17
  • 40. Path Enumeration Model Depth of the node • LENGTH(path_string) / LENGTH(emp_id) 17
  • 41. Path Enumeration Model Depth of the node • LENGTH(path_string) / LENGTH(emp_id) • LENGTH(path_string) - LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1 17
  • 42. Path Enumeration Model Depth of the node • LENGTH(path_string) / LENGTH(emp_id) • LENGTH(path_string) - LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1 17
  • 43. Path Enumeration Model Depth of the node • LENGTH(path_string) / LENGTH(emp_id) • LENGTH(path_string) - LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1 Searching for subordinates 17
  • 44. Path Enumeration Model Depth of the node • LENGTH(path_string) / LENGTH(emp_id) • LENGTH(path_string) - LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1 Searching for subordinates • SELECT * FROM emp_orgchart WHERE path_string LIKE ‘%’ || :parent_emp_id || ‘%’; 17
  • 45. Path Enumeration Model Depth of the node • LENGTH(path_string) / LENGTH(emp_id) • LENGTH(path_string) - LENGTH(REPLACE(path_string, ‘/’, ‘’)) + 1 Searching for subordinates • SELECT * FROM emp_orgchart WHERE path_string LIKE ‘%’ || :parent_emp_id || ‘%’; • SELECT * FROM emp_orgchart WHERE path_string LIKE (SELECT path_string FROM emp_orgchart WHERE emp_id = :parent_emp_id) || ‘%’; 17
  • 46. Path Enumeration Model Searching for superiors SELECT SUBSTRING(P1.path_string FROM seq * LENGTH(P1.emp_id) FOR LENGTH(P1.emp_id)) AS emp_id FROM emp_orgchart AS P1, sequence AS S1 WHERE P1.emp_id = :search_emp_id AND S1.seq <= LENGTH(path_string)/ LENGTH(emp_id); 18
  • 47. Path Enumeration Model Deleting a subtree: DELETE FROM emp_orgchart WHERE path_string LIKE ( SELECT path_string FROM emp_orgchart WHERE emp_id = :deleted_node) || ‘%’; Deleting a single node: START TRANSACTION; DELETE FROM emp_orgchart WHERE emp_id = :deleted_node; UPDATE emp_orgchart SET path_string = REPLACE(path_string, :deleted_node, ‘’); COMMIT; 19
  • 48. Path Enumeration Model Insertion of a new node INSERT INTO emp_orgchart VALUES ( :new_emp_id, -- ‘M’ :new_name, -- ‘Maggie’ (SELECT path_string FROM emp_orgchart WHERE emp_id = :boss_of_new_emp) -- ‘D’ || :new_emp_id -- ‘M’ ); emp_id emp_name path_string D Denise ACD M Maggie ACDM 20
  • 49. Path Enumeration Model Insertion of a new node INSERT INTO emp_orgchart VALUES ( :new_emp_id, -- ‘M’ :new_name, -- ‘Maggie’ (SELECT path_string FROM emp_orgchart WHERE emp_id = :boss_of_new_emp) -- ‘D’ || :new_emp_id -- ‘M’ ); emp_id emp_name path_string D Denise ACD M Maggie ACDM 20
  • 50. Path Enumeration Model Insertion of a new node INSERT INTO emp_orgchart VALUES ( :new_emp_id, -- ‘M’ :new_name, -- ‘Maggie’ (SELECT path_string FROM emp_orgchart WHERE emp_id = :boss_of_new_emp) -- ‘D’ || :new_emp_id -- ‘M’ ); emp_id emp_name path_string D Denise ACD M Maggie ACDM 20
  • 51. Path Enumeration Model Splitting the path string into nodes SELECT CASE WHEN SUBSTRING(‘/’ || P1.path_string || ‘/’ FROM S1.seq FOR 1) = ‘/’ THEN SUBSTRING(‘/’ || P1.path_string || ‘/’ FROM (S1.seq + 1) FOR CharIndex(‘/’ , ‘/’ || P1.path_string || ‘/’, S1.seq + 1) - S1.seq - 1 ELSE NULL END AS emp_id FROM sequence AS S1, emp_orgchart AS P1 WHERE S1.seq BETWEEN 1 AND LENGTH(P1.path_string) + 1 AND SUBSTRING(‘/’ || P1.path_string || ‘/’ FROM S1.seq FOR 1) = ‘/’ 21
  • 52. Path Enumeration Model emp_name edge_path Edge Anthony 1. Beryl 1.1. Enumeration Charles 1.2. Model Denise 1.2.1. Ellen 1.2.2. Frank 1.2.3. Anthony Beryl Charles Denise Ellen Frank 22
  • 53. Nested Set Model aka Modified Preorder Tree Traversal (MPTT) 23
  • 54. Nested Set Model A C B D E F 24
  • 55. Nested Set Model A C B D E F A 1 12 B C 2 3 4 11 D E F 5 6 7 8 9 10 24
  • 56. Nested Set Model CREATE TABLE orgchart ( emp VARCHAR(10) NOT NULL PRIMARY KEY, lft INTEGER NOT NULL, rgt INTEGER NOT NULL ); A 1 12 B C 2 3 4 11 D E F 5 6 7 8 9 10 25
  • 57. Nested Set Model CREATE TABLE orgchart ( emp VARCHAR(10) NOT NULL PRIMARY KEY, lft INTEGER NOT NULL, rgt INTEGER NOT NULL ); A 1 12 B C 1 A 12 2 3 4 11 D E F 5 6 7 8 9 10 2 B 3 4 C 11 D E F 5 6 7 8 9 10 25
  • 58. Nested Set Model Finding root node 1 A 12 2 B 3 4 C 11 D E F 5 6 7 8 9 10 26
  • 59. Nested Set Model Finding root node SELECT * FROM orgchart WHERE lft = 1; 1 A 12 2 B 3 4 C 11 D E F 5 6 7 8 9 10 26
  • 60. Nested Set Model Finding root node SELECT * FROM orgchart WHERE lft = 1; 1 A 12 Finding leaf nodes 2 B 3 4 C 11 D E F 5 6 7 8 9 10 26
  • 61. Nested Set Model Finding root node SELECT * FROM orgchart WHERE lft = 1; 1 A 12 Finding leaf nodes SELECT * 2 B 3 4 C 11 FROM orgchart WHERE lft = (rgt - 1); D E F 5 6 7 8 9 10 26
  • 62. Nested Set Model Finding root node SELECT * FROM orgchart WHERE lft = 1; 1 A 12 Finding leaf nodes SELECT * 2 B 3 4 C 11 FROM orgchart WHERE lft = (rgt - 1); D E F Finding subtrees 5 6 7 8 9 10 26
  • 63. Nested Set Model Finding root node SELECT * FROM orgchart WHERE lft = 1; 1 A 12 Finding leaf nodes SELECT * 2 B 3 4 C 11 FROM orgchart WHERE lft = (rgt - 1); D E F Finding subtrees 5 6 7 8 9 10 SELECT Mgrs.emp AS boss Workers.emp AS worker FROM orgchart AS Mgrs, orgchart AS Workers WHERE Workers.lft > Mgrs.lft AND Workers.lft < Mgrs.rgt 26
  • 64. Nested Set Model Finding root node SELECT * FROM orgchart WHERE lft = 1; 1 A 12 Finding leaf nodes SELECT * 2 B 3 4 C 11 FROM orgchart WHERE lft = (rgt - 1); D E F Finding subtrees 5 6 7 8 9 10 SELECT Mgrs.emp AS boss Workers.emp AS worker FROM orgchart AS Mgrs, orgchart AS Workers WHERE Workers.lft > Mgrs.lft BETWEEN Mgrs.lft AND Mgrs.rgt AND Workers.lft < Mgrs.rgt 26
  • 65. Nested Set Model Finding the level of a node 27
  • 66. Nested Set Model Finding the level of a node SELECT o2.emp, COUNT(o1.emp) AS lvl FROM orgchart AS o1, orgchart AS o2 WHERE o2.lft BETWEEN o1.lft AND o1.rgt GROUP BY o2.emp; 27
  • 67. Nested Set Model Finding the level of a node SELECT o2.emp, COUNT(o1.emp) AS lvl FROM orgchart AS o1, orgchart AS o2 WHERE o2.lft BETWEEN o1.lft AND o1.rgt GROUP BY o2.emp; Finding the height of the tree 27
  • 68. Nested Set Model Finding the level of a node SELECT o2.emp, COUNT(o1.emp) AS lvl FROM orgchart AS o1, orgchart AS o2 WHERE o2.lft BETWEEN o1.lft AND o1.rgt GROUP BY o2.emp; Finding the height of the tree SELECT MAX(lvl) AS height FROM ( SELECT o2.emp, COUNT(o1.emp) - 1 FROM orgchart AS o1, orgchart AS o2 WHERE o2.lft BETWEEN o1.lft AND o1.rgt GROUP BY o2.emp) AS L1(emp, lvl); 27
  • 69. Nested Set Model Finding relative position SELECT CASE WHEN :emp1 = :emp2 THEN :emp1 || ‘ is ’ || :emp2 WHEN o1.lft BETWEEN o2.lft AND o2.rgt THEN :emp1 || ‘ subordinate to ’ || :emp2 WHEN o2.lft BETWEEN o1.lft AND o1.rgt THEN :emp2 || ‘ subordinate to ’ || :emp1 ELSE :emp1 || ‘ no relation to ’ || :emp2 END FROM orgchart AS o1, orgchart AS o2 WHERE o1.emp = :emp1 AND o2.emp = :emp2; 28
  • 70. Nested Set Model Deleting subtrees DELETE FROM orgchart WHERE lft BETWEEN (SELECT lft FROM orgchart WHERE emp = :start_node) AND (SELECT rgt FROM orgchart Filling gaps WHERE emp = :start_node); CREATE VIEW LftRgt (seq) AS SELECT lft FROM orgchart UNION ALL SELECT rgt FROM orgchart; UPDATE orgchart SET lft = (SELECT COUNT(*) FROM LftRgt WHERE seq <= lft), rgt = (SELECT COUNT(*) FROM LftRgt WHERE seq <= rgt) 29
  • 71. Nested Set Model Deleting a single node DELETE FROM orgchart WHERE emp = ‘C’; A C B D E F 30
  • 72. Nested Set Model Deleting a single node DELETE FROM orgchart WHERE emp = ‘C’; A B D E F 30
  • 73. Nested Set Model Deleting a single node CREATE PROCEDURE downsize(IN removed VARCHAR(10)) LANGUAGE SQL DETERMINISTIC UPDATE orgchart SET emp = CASE WHEN orgchart.emp = removed AND orgchart.lft + 1 = orgchart.rgt --leaf THEN ‘{vacant}’ WHEN orgchart.emp = removed AND orgchart.lft + 1 <> orgchart.rgt -- promote subordinate and vacate THEN (SELECT o1.emp FROM orgchart AS o1 WHERE orgchart.lft + 1 = o1.lft) WHEN orgchart.emp = (SELECT o1.emp FROM orgchart AS o1 WHERE orgchart.lft + 1 = o1.lft) THEN ‘{vacant}’ ELSE emp END; 31
  • 74. Nested Set Model Deleting a single node CREATE PROCEDURE downsize(IN removed VARCHAR(10)) LANGUAGE SQL DETERMINISTIC UPDATE orgchart SET emp = CASE WHEN orgchart.emp = removed AND orgchart.lft + 1 = orgchart.rgt --leaf THEN ‘{vacant}’ WHEN orgchart.emp = removed AND orgchart.lft + 1 <> orgchart.rgt -- promote subordinate and vacate THEN (SELECT o1.emp FROM orgchart AS o1 WHERE orgchart.lft + 1 = o1.lft) WHEN orgchart.emp = (SELECT o1.emp FROM orgchart AS o1 WHERE orgchart.lft + 1 = o1.lft) THEN ‘{vacant}’ ELSE emp END; 31
  • 75. Nested Set to Adjacency List SELECT B.id AS boss, P.emp, P.lft, P.rgt FROM orgchart as P LEFT OUTER JOIN emp AS B ON B.lft = (SELECT MAX(S.lft) FROM orgchart AS S WHERE P.lft > S.lft AND P.lft < S.rgt); boss emp lft rgt NULL Anthony 1 12 Anthony Beryl 2 3 Anthony Charles 4 11 Charles Denise 5 6 Charles Ellen 7 8 Charles Frank 9 10 32
  • 76. Frequent Insertion Trees Avoid overhead (locking + updating) with larger spreads and bigger gaps emp lft rgt Anthony 100 1200 Beryl 200 300 Charles 400 1100 Denise 500 600 Ellen 700 800 Frank 900 1000 33
  • 77. Frequent Insertion Trees Avoid overhead (locking + updating) with larger spreads and bigger gaps emp lft rgt Anthony 100 1200 Beryl 200 300 Charles 400 1100 Denise 500 600 Ellen 700 800 Frank 900 1000 Datatype of (lft, rgt)? - INTEGER (full range) - FLOAT / REAL / DOUBLE - NUMERIC(p,s) / DECIMAL(p,s) 33
  • 78. Frequent Insertion Trees Avoid overhead (locking + updating) with larger spreads and bigger gaps emp lft rgt Anthony 100 1200 Beryl 200 300 Charles 400 1100 Denise 500 600 Ellen 700 800 Frank 900 1000 Datatype of (lft, rgt)? - INTEGER (full range) - FLOAT / REAL / DOUBLE - NUMERIC(p,s) / DECIMAL(p,s) 33
  • 79. Frequent Insertion Trees Avoid overhead (locking + updating) with larger spreads and bigger gaps emp lft rgt Anthony 100 1200 Beryl 200 300 Charles 400 1100 Denise 500 600 Ellen 700 800 Frank 900 1000 Datatype of (lft, rgt)? - INTEGER (full range) - FLOAT / REAL / DOUBLE - NUMERIC(p,s) / DECIMAL(p,s) 33
  • 80. Frequent Insertion Trees Avoid overhead (locking + updating) with larger spreads and bigger gaps emp lft rgt Anthony 100 1200 Beryl 200 300 Charles 400 1100 Denise 500 600 Ellen 700 800 Frank 900 1000 Datatype of (lft, rgt)? - INTEGER (full range) - FLOAT / REAL / DOUBLE - NUMERIC(p,s) / DECIMAL(p,s) 33
  • 81. Hybrid Models Adjacency List with Nested Sets (node, parent, lft, rgt) Nested Sets with depth Adjacency List with depth ... Denormalisation to save subselects or joins 34
  • 83. Nested Intervals Model Rational numbers (a/b, with a and b integers) ((p.lft <= c.lft) AND (c.rgt <= p.rgt)) 0/5 A 5/5 1/5 B 2/5 3/5 C 4/5 36
  • 85. Nested Intervals Model a b a+(b-a)/3 a+2(b-a)/3 37
  • 86. Nested Intervals Model Finding GCD (greatest common divisor) CREATE FUNCTION gcd(IN x INTEGER, IN y INTEGER) RETURNS INTEGER LANGUAGE SQL DETERMINISTIC BEGIN WHILE x <> y DO IF x > y THEN SET x = x - y; END IF; IF y > x THEN SET y = y - x; END IF; END WHILE; RETURN x; END; 38
  • 87. Nested Intervals Model Binary Node (x, y) Fractions 39
  • 88. Nested Intervals Model Binary Node (x, y) Fractions First node (1, 1/2) 39
  • 89. Nested Intervals Model Binary Node (x, y) Fractions First node (1, 1/2) depth-first convergence point 39
  • 90. Nested Intervals Model Binary Node (x, y) Fractions First child of first node (1, 3/4) First node (1, 1/2) depth-first convergence point 39
  • 91. Nested Intervals Model Binary Node (x, y) Fractions First child of first node (1, 3/4) First node (1, 1/2) depth-first convergence point breadth-first convergence point 39
  • 92. Nested Intervals Model Binary Node (x, y) Fractions First child of first node (1, 3/4) First node (1, 1/2) depth-first convergence point breadth-first convergence point 39
  • 93. Nested Intervals Model Binary Node (x, y) Fractions First child of first node (1, 3/4) First node (1, 1/2) depth-first convergence point breadth-first convergence point 39
  • 95. Nested Intervals Model CREATE FUNCTION x_numer( IN numer INT, IN denom INT ) RETURNS INTEGER BEGIN DECLARE ret_num INTEGER; DECLARE ret_den INTEGER; SET ret_num = numer + 1; SET ret_den = 2 * denom; WHILE FLOOR(ret_num/2) = ret_num/2 DO SET ret_num = ret_num/2; SET red_den = ret_den/2; END WHILE; RETURN ret_num; -- ret_den -- for x_denom() END; 40
  • 96. Nested Intervals Model CREATE FUNCTION parent_numer(IN numer INTEGER, IN denom INTEGER) RETURNS INTEGER LANGUAGE SQL DETERMINISTIC BEGIN DECLARE ret_num INTEGER; DECLARE ret_den INTEGER; IF numer = 3 THEN RETURN CAST(NULL AS INTEGER) END IF; SET ret_num = (numer - 1)/2; SET ret_den = denom/2; WHILE FLOOR((ret_num - 1)/4) = (ret_num - 1)/4 DO SET ret_num = (ret_num + 1)/2; SET red_den = ret_den/2; END WHILE; RETURN ret_num; -- ret_den for parent_denom() END; 41
  • 97. Nested Intervals Model Similar functions for: sibling_numer(), sibling_denom() child_numer(), child_denom() enumerated_path(), distance() path_numer(), path_denom() 42
  • 98. Nested Intervals Model Similar functions for: sibling_numer(), sibling_denom() child_numer(), child_denom() enumerated_path(), distance() path_numer(), path_denom() INSERT INTO orgchart (name, numer, denom) VALUES (‘Anthony’, path_numer(‘1’), path_denom(‘1’)), (‘Beryl’, path_numer(‘1.1’), path_denom(‘1.1’)), (‘Charles’, path_numer(‘1.2’), path_denom(‘1.2’)), (‘Denise’, path_numer(‘1.2.1’), path_denom(‘1.2.1’)); 42
  • 99. Nested Intervals Encodings Interval Halving average: (lft + rgt) / 2 43
  • 100. Nested Intervals Encodings Interval Halving average: (lft + rgt) / 2 Farey Fractions a/b and c/d neighbours => bc -ad = 1 mediant: (lft_num + rgt_num) (lft_den + rgt_den) 43
  • 101. Nested Intervals Encodings Continued Fractions 1.1.2.1 Reverse (or additive) Continued Fractions 44
  • 103. Oracle: CONNECT BY PRIOR Traversing the tree SELECT emp, boss FROM emp_orgchart START WITH boss IS NULL CONNECT BY [NOCYCLE] PRIOR emp = boss; emp boss A NULL B A G B C A D C E C F C 46
  • 104. Oracle: CONNECT BY PRIOR Traversing the tree SELECT emp, boss FROM emp_orgchart START WITH boss = ‘C’ IS NULL CONNECT BY [NOCYCLE] PRIOR emp = boss; emp boss D C E C F C 46
  • 105. Oracle: CONNECT BY PRIOR Traversing the tree SELECT emp, boss, salary, LEVEL AS lvl, LPAD(' ', 2*(LEVEL-1)) || emp AS tree, CONNECT_BY_IS_LEAF AS is_leaf FROM emp_orgchart CONNECT BY PRIOR emp = boss START WITH boss IS NULL ORDER SIBLINGS BY salary DESC; emp boss salary lvl tree is_leaf A NULL 1000.00 1 A 0 B A 900.00 2 B 0 G B 800.00 3 G 1 C A 900.00 2 C 0 D C 800.00 3 D 1 E C 700.00 3 E 1 F C 600.00 3 F 1 47
  • 106. Oracle: CONNECT BY PRIOR Determining the relationship between two nodes SELECT COUNT(*) AS ‘is_subordinate’ FROM emp_orgchart WHERE emp = :subordinate AND LEVEL > 1 START WITH emp = :superior CONNECT BY PRIOR emp = boss; 48
  • 107. Oracle: CONNECT BY PRIOR Determining the relationship between two nodes SELECT COUNT(*) AS ‘is_subordinate’ FROM emp_orgchart WHERE emp = :subordinate AND LEVEL > 1 START WITH emp = :superior CONNECT BY PRIOR emp = boss; A subordinate of C? 0 F subordinate of A? 1 48
  • 108. Oracle: CONNECT_BY_ROOT Determining the ancestor of a node SELECT emp_id, CONNECT_BY_ROOT emp_id AS root FROM orgchart START WITH boss = ‘A’ CONNECT BY PRIOR emp_id = boss; emp_id root B B G B C C D C E C F C 49
  • 109. Oracle: SYS_CONNECT_BY_PATH Materialized Path View SELECT emp_id, SYS_CONNECT_BY_PATH (emp_id,'.') AS path_string FROM orgchart START WITH boss IS NULL CONNECT BY PRIOR emp_id = boss ORDER BY 2; emp_id path_string A .A B .A.B C .A.C D .A.C.D E .A.C.E F .A.C.F 50
  • 111. Common Table Expressions CREATE TABLE emp_orgchart ( emp VARCHAR(10) PRIMARY KEY, boss VARCHAR(10) REFERENCES emp_orgchart(emp_id), salary TEXT ); INSERT INTO emp_orgchart (emp, boss, salary) VALUES (‘A’, NULL, 1000.00), (‘B’, ‘A’, 900.00), (‘C’, ‘A’, 900.00), A (‘D’, ‘C’, 800.00), (‘E’, ‘C’, 700.00), (‘F’, ‘C’, 600.00), B C (‘G’, ‘B’, 800.00); G D E F 52
  • 112. Common Table Expressions WITH RECURSIVE hierarchy AS ( -- non recursive term SELECT * FROM emp_orgchart WHERE boss IS NULL UNION ALL -- recursive term SELECT E1.* FROM emp_orgchart AS E1 JOIN hierarchy AS E2 ON E1.boss = E2.emp ) SELECT * FROM hierarchy ORDER BY emp; 53
  • 113. Common Table Expressions WITH RECURSIVE hierarchy AS ( -- non recursive term SELECT * FROM emp_orgchart WHERE boss IS NULL UNION ALL -- recursive term SELECT E1.* FROM emp_orgchart AS E1 JOIN hierarchy AS E2 ON E1.boss = E2.emp ) SELECT * FROM hierarchy ORDER BY emp; 53
  • 114. Common Table Expressions WITH RECURSIVE hierarchy AS ( -- non recursive term SELECT * FROM emp_orgchart WHERE boss IS NULL UNION ALL -- recursive term SELECT E1.* FROM emp_orgchart AS E1 JOIN hierarchy AS E2 ON E1.boss = E2.emp ) SELECT * FROM hierarchy ORDER BY emp; 53
  • 115. Common Table Expressions WITH RECURSIVE hierarchy AS ( -- non recursive term SELECT * FROM emp_orgchart WHERE boss IS NULL emp boss salary UNION ALL A NULL 1000.00 -- recursive term B A 900.00 SELECT E1.* C A 900.00 FROM emp_orgchart AS E1 D C 800.00 JOIN hierarchy AS E2 E C 700.00 ON E1.boss = E2.emp F C 600.00 ) SELECT * G B 800.00 FROM hierarchy ORDER BY emp; 53
  • 116. Common Table Expressions WITH RECURSIVE hierarchy AS ( SELECT *, 1 AS lvl, CAST(emp AS TEXT) AS tree, emp || ‘.’ AS path FROM emp_orgchart WHERE boss IS NULL UNION ALL SELECT E1.*, E2.lvl + 1 AS lvl, LPAD(E1.emp, lvl * 2, ‘ ’) AS tree, E2.path || E1.emp || ‘.’ AS path FROM emp_orgchart JOIN hierarchy AS E2 ON E1.boss = E2.emp ) SELECT * FROM hierarchy ORDER BY path; 54
  • 117. Common Table Expressions WITH RECURSIVE hierarchy AS ( SELECT *, 1 AS lvl, CAST(emp AS TEXT) AS tree, emp || ‘.’ AS path FROM emp_orgchart WHERE boss IS NULL UNION ALL SELECT E1.*, E2.lvl + 1 AS lvl, LPAD(E1.emp, lvl * 2, ‘ ’) AS tree, E2.path || E1.emp || ‘.’ AS path FROM emp_orgchart JOIN hierarchy AS E2 ON E1.boss = E2.emp ) SELECT * FROM hierarchy ORDER BY path; 54
  • 118. Common Table Expressions WITH RECURSIVE hierarchy AS ( SELECT *, 1 AS lvl, CAST(emp AS TEXT) AS tree, emp || ‘.’ AS path FROM emp_orgchart WHERE boss IS NULL UNION ALL SELECT E1.*, E2.lvl + 1 AS lvl, LPAD(E1.emp, lvl * 2, ‘ ’) AS tree, E2.path || E1.emp || ‘.’ AS path FROM emp_orgchart JOIN hierarchy AS E2 ON E1.boss = E2.emp ) SELECT * FROM hierarchy ORDER BY path; 54
  • 119. Common Table Expressions WITH RECURSIVE hierarchy AS ( SELECT *, 1 AS lvl, CAST(emp AS TEXT) AS tree, emp || ‘.’ AS path FROM emp_orgchart WHERE boss IS NULL UNION ALL SELECT E1.*, E2.lvl + 1 AS lvl, LPAD(E1.emp, lvl * 2, ‘ ’) AS tree, E2.path || E1.emp || ‘.’ AS path FROM emp_orgchart JOIN hierarchy AS E2 ON E1.boss = E2.emp ) SELECT * FROM hierarchy ORDER BY path; 54
  • 120. Common Table Expressions WITH RECURSIVE hierarchy AS ( SELECT *, 1 AS lvl, CAST(emp AS TEXT) AS tree, emp || ‘.’ AS path FROM emp_orgchart WHERE boss IS NULL UNION ALL SELECT E1.*, E2.lvl + 1 AS lvl, LPAD(E1.emp, lvl * 2, ‘ ’) AS tree, E2.path || E1.emp || ‘.’ AS path FROM emp_orgchart JOIN hierarchy AS E2 ON E1.boss = E2.emp ) SELECT * FROM hierarchy ORDER BY path; 54
  • 121. Common Table Expressions WITH RECURSIVE hierarchy AS ( SELECT *, 1 AS lvl, emp CAST(emp salary boss AS TEXT) AS tree, tree lvl path emp || ‘.’ AS path A NULL 1000.00 1 A A. FROM emp_orgchart WHERE boss IS NULL B A 900.00 2 B A.B. UNION ALL SELECT E1.*, G B 800.00 3 G A.B.G. E2.lvl + 1 AS lvl, C LPAD(E1.emp, lvl * 2, ‘ ’)CAS tree, A 900.00 2 A.C. E2.path || E1.emp || ‘.’ AS path D C 800.00 FROM emp_orgchart 3 D A.C.D. JOIN hierarchy AS E2 E C 700.00 3 E A.C.E. ON E1.boss = E2.emp ) F C 600.00 3 F A.C.F. SELECT * FROM hierarchy ORDER BY path; 54
  • 122. Common Table Expressions WITH RECURSIVE hierarchy AS ( SELECT *, 1 AS lvl, CAST(emp AS TEXT) AS tree FROM emp_orgchart WHERE boss = ‘A’ UNION ALL SELECT E1.*, E2.lvl + 1 AS lvl, LPAD(E1.emp, depth * 2, ‘ ’) AS tree FROM emp_orgchart JOIN hierarchy AS E2 ON E1.boss = E2.emp WHERE E2.lvl < 3 -- termination condition ) SELECT * FROM hierarchy ORDER BY path; 55
  • 123. Common Table Expressions WITH RECURSIVE hierarchy AS ( SELECT *, 1 AS lvl, CAST(emp AS TEXT) AS tree FROM emp_orgchart WHERE boss = ‘A’ UNION ALL SELECT E1.*, E2.lvl + 1 AS lvl, LPAD(E1.emp, depth * 2, ‘ ’) AS tree FROM emp_orgchart JOIN hierarchy AS E2 ON E1.boss = E2.emp ) SELECT *, COALESCE((SELECT 0 FROM emp_orgchart E3 WHERE hierarchy.emp = E3.boss FETCH FIRST ROW ONLY), 1) AS is_leaf FROM hierarchy; 56
  • 124. And the winner is... 57
  • 125. And the winner is... 57
  • 126. Questions ? 58
  • 127. Resources Joe Celko, “Trees and Hierarchies in SQL for Smarties”, Morgan Kaufmann: http://www.amazon.com/dp/1558609202/ Vadim Tropashko, various articles and papers: http://www.dbazine.com/top-auth/top-auth-trop/ http://www.sigmod.org/sigmod/record/issues/ 0506/p47-article-tropashko.pdf http://arxiv.org/pdf/cs/0402051 59
  • 128. Thank you! Contact details: Lorenzo Alberton lorenzo@ibuildings.com http://www.alberton.info http://joind.in/talk/view/585