【问题标题】:Hierarchical structure for concrete id具体id的层次结构
【发布时间】:2019-11-05 02:00:31
【问题描述】:

我有一个递归数据库表和所有表数据的分层视图

CREATE VIEW dbo.vw_hierarchicalView
AS
    WITH hView (Id,
                    IdParent,
                    Level)
    AS
    (
        SELECT tableParent.Id,
               tableParent.IdParent,
               1 AS Level
        FROM dbo.vw_ComplaintWithStatus tableParent
        WHERE tableParent.IdParent IS NULL
        UNION ALL SELECT tableChild.Id,
                         tableChild.IdParent,
                         hw.level + 1 AS  Level
                 FROM dbo.vw_ComplaintWithStatus tableChild
                      INNER JOIN hView hw ON  tableChild.IdParent = hw.Id
    )
    SELECT final.Id,
           final.IdParent,
           ISNULL(final.Level, 1) AS Level
    FROM hView final

当我查询所有数据时,所有的树都是正确的。

SELECT * FROM dbo.vw_hierarchicalView hw ORDER BY hw.Level, hw.Id

但是,如果我只想为一个 id 选择完整的树,查询只显示具有指定 id 的第一行

SELECT * FROM dbo.vw_hierarchicalView hw WHERE hw.Id = 5 ORDER BY hw.Level, hw.Id

我想在我的应用程序中使用它来使用实体框架查找树中的所有子记录。

应用逻辑返回给我一些记录,需要查找:

  1. 仅限第一个直接子记录
  2. 所有子记录(用于在网页中显示树)

I 类从视图中选择存储过程,并将 Id 作为此过程的参数,并在 WHERE tableParent.Id = @id 上替换条件 WHERE tableParent.IdParent IS NULL。此解决方案效果很好,但是...

我不想使用存储过程。

在没有数据库函数或过程的情况下,有什么方法可以解决这个问题吗?

【问题讨论】:

    标签: sql-server tsql sql-server-2014


    【解决方案1】:

    你可以使用表值函数:

    CREATE FUNCTION my_func(@root_id INT)
    RETURNS TABLE
    AS
    RETURN
    WITH hView (Id,IdParent,Level) AS
        (
            SELECT tableParent.Id,
                   tableParent.IdParent,
                   1 AS Level
            FROM dbo.vw_ComplaintWithStatus tableParent
            WHERE (tableParent.IdParent IS NULL  AND @root_id IS NULL)
               OR Id = @root_id
            UNION ALL SELECT tableChild.Id,
                             tableChild.IdParent,
                             hw.level + 1 AS  Level
                     FROM dbo.vw_ComplaintWithStatus tableChild
                          INNER JOIN hView hw ON  tableChild.IdParent = hw.Id
        )
        SELECT final.Id,
               final.IdParent,
               ISNULL(final.Level, 1) AS Level
        FROM hView final;
    

    呼叫:

    SELECT * FROM dbo.my_func(NULL) hw ORDER BY hw.Level, hw.Id;
    --
    SELECT * FROM dbo.my_func(5) hw ORDER BY hw.Level, hw.Id;
    

    【讨论】:

    • 我现在已经通过存储过程做到了。我对没有功能或程序的解决方案感兴趣。如果可以的话……
    • @Davecz TVP 函数基本上是参数化视图,它是处理此类场景的正确方法Can we pass parameters to a view in SQL?
    • @Davecz TVP 函数相对于存储过程的最大优势在于您可以轻松地将其与其他查询组合(这里只是 FROM 子句的一部分),您仍然可以添加其他 WHERE 条件或将其包装子查询。
    • 我知道,但是可以在实体框架的 where 条件下调用函数吗?例如 var data = from d in DbSet where DataContext.MyFunction(d.Id) select d;我不确定
    • @Davecz 我不是 EF 的专家,但我想应该在实体类级别上有注释,如 query/...。至少这样的事情在休眠状态下是可能的。您应该开始一个新问题如何将 EntityFramework 映射到 SQL 函数调用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    • 2011-10-13
    • 1970-01-01
    • 2019-11-19
    相关资源
    最近更新 更多