过滤递归 sql 查询与可能的和选择的项目相交

Filtering recursive sql query intersecting possible and choosen items

在Sql服务器中我有以下场景:

  1. 选项和相关组:

    Groups(Id, Description)
    Options(Id, GroupId, Description)
    
  2. 配置了选项的节点:

    Nodes(Id, ParentNodeId, Description)
    Configurations(Id, NodeId, OptionId)
    

所以一个节点可以有一个或多个选项,但每组一个

  1. 用户选择:

    Choices (Guid, OptionId)
    

在输出中,我希望以递归方式使用选择选项配置节点。 例如:

Groups
1, "Eyes Color"
2, "Hair Color"
Options
1, 1, "Blue"
2, 1, "Brown"
3, 2, "Blonde"
4, 2, "Black"
Nodes
1, NULL, "Elizabeth"
2, NULL, "John"
Configurations
1, 1, 1 --(Elizabeth, Blue)
1, 1, 3 --(Elizabeth, Blonde)
2, 1, 4 --(John, Black)

可能的选择:

Eyes Color: NULL  -- it means there isn't record in choices table for this option
Hair Color: NULL
Result: Elizabeth, John
Eyes Color: "Blue"
Hair Color: NULL
Result: Elizabeth, John
Eyes Color: "Brown"
Hair Color: NULL
Result: John
Eyes Color: NULL
Hair Color: "Blonde"
Result: Elizabeth
Eyes Color: NULL
Hair Color: "Black"
Result: John
Eyes Color: "Blue"
Hair Color: "Black"
Result: John
Eyes Color: "Blue"
Hair Color: "Blonde"
Result: Elizabeth
Eyes Color: "Brown"
Hair Color: "Blonde"
Result: -
Eyes Color: "Brown"
Hair Color: "Black"
Result: John

我的第一个问题是过滤。第二个问题是在递归中过滤不分析节点是不包括节点的子节点。

递归:

with livelliRec
as
(
   select 
   0 as level, nodeid, parentid
   from nodes

   union all

   select 
   livellirec.level+1, nodes.nodeid, nodes.parentid
   from nodes
   join livelliRec on nodes.parentid = livellirec.nodeid
)

我找到了一个可能的解决方案,当一个节点没有为该组配置时列出所有可能的项目,然后验证所有选择的项目都在可能的项目中。但是如何编写查询来执行呢?

提前致谢。

在我的示例中,如果没有为组配置节点,它将被选中:

;WITH Filtered AS (
    SELECT N.Id, N.ParentId
    FROM nodes    N
    WHERE NOT EXISTS (
        SELECT 1 
        FROM configurations     C
        INNER JOIN Options      C_OP  ON C_OP.OptionId = C.OptionId
        INNER JOIN Options      CH_OP ON CH_OP.GroupId  = C_OP.GroupId
        INNER JOIN Choises      CH    ON CH.OptionId = CH_OP.OptionId 
        WHERE C.NodeId = N.Id AND CH.OptionId <> C.OptionId 
    )
), cte AS (
    SELECT 0 AS Level, Id, ParentId
    FROM Filtered 
    WHERE ParentId IS NULL

    UNION ALL

    SELECT cte.Level + 1 AS Level, Id, ParentId
    FROM Filtered  F
    INNER JOIN cte ON F.ParentId = cte.Id
)
SELECT DISTINCT cte.Id
FROM cte