简体   繁体   中英

Cascade funtions SQL to go from tree structure to flat data structure

I have 2 tables :

table1 t_SearchCriteria:

------------------------------
ID   |  VALUE     | IDParent   |
-----|------------|------------|
 0   |   root     |     -1     |
-----|------------|------------|
 1   | JAMES      |      0     |
-----|------------|------------|
 2   | ISAC       |      0     |
-----|------------|------------|
 3   | LISA       |      1     |
-----|------------|------------|
 4   | Andrew     |      3     |
-----|------------|------------|
 5   | LISA       |      2     |
-----|------------|------------|
 6   | EZREAL     |      5     |
-----|------------|------------|
 10  | twitch     |      2     |
-----|------------|------------|
 13  | LUX        |      0     |
-----|------------|------------|
 14  | LISA       |      13    |
-----|------------|------------|
 15  | EZREAL     |      14    |
-----|------------|------------|

EDIT: here is a representation of the tree:

                                            _______root_______
                                           /        |         \
                                       JAMES       ISAC       LUX
                                         |        /   \         |
                                        LISA   TWITCH  LISA    LISA
                                         |              |       |
                                       Andrew        EZREAL   EZREAL

and my second table is like the following :

table t_Path

idPath|Person1|  Son  |grandSon|grandgrandSon|
------|-------|-------|--------|-------------|
   1  |root   |JAMES  | LISA   |ANDREW       |
------|-------|-------|--------|-------------|
   2  |root   |ISAC   | LISA   |EZREAL       |
------|-------|-------|--------|-------------|
   3  |root   |ISAC   | NULL   |TWITCH       |
------|-------|-------|--------|-------------|
   4  |root   |LUX    | NULL   |  NULL       |
------|-------|-------|--------|-------------|
   5  |root   |LUX    | LISA   |  NULL       |
------|-------|-------|--------|-------------|
   6  |root   |LUX    | LISA   | EZREAL      |
------|-------|-------|--------|-------------|

My need is to figure out a way (function or procedure) that starts from table 2 (t_Path) and find each leaf (value of grandgrandSon if not null otherwise grandson if not null etc...) id in t_searchCriteria table:

Since we can have the same value of node in the t_search criteria table then the unicity of a node is its value and its parent value and its grandParentValue (and we have another rule; a parent can't have 2 childs with same name)

I have tried to make a function but i didn't find a way to do a function inside another function besides working with objects like in c# or another programming laguage.

I need to make a function that takes an int ID wich is the ID of a path from table t_Path and figure out the leaf of the path (this is done), the problem here is how to get the id of that leaf from t_searchCriteria table since we can have multiple criterias with same value (name) even with same parent name, the grandParent Value will make difference.

for example of execution: Select FunctionGetCriteriaId(6) will return 15

where 6 is the id of the path : 6 |root |LUX | LISA | EZREAL | 6 |root |LUX | LISA | EZREAL |

and 15 is the id of the criteria : 15 | EZREAL | 14 | 15 | EZREAL | 14 |

Can anyone help me to figure this out please?

EDIT: to be more specific the fucntion takes the id of the path in table 2, for example 5 ( 5 |root |LUX | LISA | NULL |) and returns the id of "LISA" (the leaf not the others ;) ) in table 1 that is 14. (ofcourse taking note of the rules set before.)

EDIT 2: updated unicity condition in the tree

You can do this easily using LEFT JOINS and MAX and COALESCE . This is full working example. You can play with it:

DECLARE @t_SearchCriteria TABLE
(
    [ID] SMALLINT
   ,[Value] VARCHAR(12)
   ,[IDParent] SMALLINT
);

INSERT INTO @t_SearchCriteria ([ID], [Value], [IDParent])
VALUES (0, 'root', -1)
      ,(1, 'JAMES', 0)
      ,(2, 'ISAC', 0)
      ,(3, 'LISA', 1)
      ,(4, 'Andrew', 3)
      ,(5, 'LISA', 2)
      ,(6, 'EZREAL', 5)
      ,(10, 'twitch', 2)
      ,(13, 'LUX',  0)
      ,(14, 'LISA', 13)
      ,(15, 'EZREAL', 14);

DECLARE @t_Path TABLE
(
    [idPath] SMALLINT
   ,[Person1] VARCHAR(12)
   ,[Son] VARCHAR(12)
   ,[grandSon] VARCHAR(12)
   ,[grandgrandSon] VARCHAR(12)
);

INSERT INTO @t_Path ([idPath], [Person1], [Son], [grandSon], [grandgrandSon])
VALUES (1, 'root', 'JAMES', 'LISA', 'ANDREW')
      ,(2, 'root', 'ISAC', 'LISA', 'EZREAL')
      ,(3, 'root', 'ISAC',  'TWITCH', NULL)
      ,(4, 'root', 'LUX', NULL, NULL)
      ,(5, 'root', 'LUX', 'LISA', NULL)
      ,(6, 'root', 'LUX', 'LISA', 'EZREAL');


-- the function input parameter
DECLARE @idPath SMALLINT = 5;

-- the function body

DECLARE @Person1 VARCHAR(12)
       ,@Son VARCHAR(12)
       ,@grandSon VARCHAR(12)
       ,@grandgrandSon VARCHAR(12);

SELECT @Person1 = [Person1]
      ,@Son = [Son]
      ,@grandSon = [grandSon]
      ,@grandgrandSon = [grandgrandSon]
FROM @t_Path P
WHERE P.[idPath] = @idPath;

SELECT COALESCE(MAX(S5.[ID]), MAX(S4.[ID]), MAX(S3.[ID]), MAX(S2.[ID]), MAX(S1.[ID]))
FROM @t_SearchCriteria S1
LEFT JOIN @t_SearchCriteria S2
    ON S1.[ID] = S2.[IDParent]
    AND S1.[Value] = @Person1
LEFT JOIN @t_SearchCriteria S3
    ON S2.[ID] = S3.[IDParent]
    AND S2.[Value] = @Son
    AND @Person1 IS NOT NULL
LEFT JOIN @t_SearchCriteria S4
    ON S3.[ID] = S4.[IDParent]  
    AND S3.[Value] = @grandSon
    AND @grandgrandSon IS NOT NULL
LEFT JOIN @t_SearchCriteria S5
    ON S4.[ID] = S5.[IDParent]
    AND S4.[Value] = @grandgrandSon
WHERE S1.[Value] = @Person1;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM