当前位置: 首页 > 面试题库 >

在C#中模拟CTE递归

赖明煦
2023-03-14
问题内容

假设具有以下CTE,这些CTE返回我已经拥有的某些树数据(邻接模型)的级别(取自Linq中的分层数据-
options和performance):

WITH hierarchy_cte(id, parent_id, data, lvl) AS
(
    SELECT id, parent_id, data, 0 AS lvl
    FROM dbo.hierarchical_table
    WHERE (parent_id IS NULL)

    UNION ALL

    SELECT t1.id, t1.parent_id, t1.data, h.lvl + 1 AS lvl
    FROM dbo.hierarchical_table AS t1 
    INNER JOIN hierarchy_cte AS h ON t1.parent_id = h.id
)
SELECT id, parent_id, data, lvl
FROM hierarchy_cte AS result

我想知道通过使用C#而不是SQL进行递归是否会提高性能。假设我有一个IQueryable,其中Tree是表示层次结构表中条目的实体,谁能向我展示如何执行CTE与递归C#函数相同的工作?类似于以下内容:

public void RecurseTree(IQueryable<Tree> tree, Guid userId, Guid parentId, int level)
{
    ...
    currentNode.level = x
    ...
    Recurse(tree... ,level + 1)
}

看到使用lambda表达式很容易做到这一点将很酷。


问题答案:

相比之下,SQL Server中的递归速度非常慢,但是确实可以正常工作。

我不得不说,T-SQL在某种程度上受到限制,但是它从来没有打算首先进行所有这些操作。我不相信如果您打算针对SQLServer实例运行IQueryable,则无法通过IQueryable来实现,但是您可以在运行代码的机器上的内存中使用LINQ-to-Objects来实现。紧凑的方式。

这是一种方法:

class TreeNode
{
    public int Id;
    public int? ParentId;
}

static void Main(string[] args)
{
    var list = new List<TreeNode>{
        new TreeNode{ Id = 1 },
            new TreeNode{ Id = 4, ParentId = 1 },
            new TreeNode{ Id = 5, ParentId = 1 },
            new TreeNode{ Id = 6, ParentId = 1 },
        new TreeNode{ Id = 2 },
            new TreeNode{ Id = 7, ParentId= 2 },
                new TreeNode{ Id = 8, ParentId= 7 },
        new TreeNode{ Id = 3 },
    };

    foreach (var item in Level(list, null, 0))
    {
        Console.WriteLine("Id={0}, Level={1}", item.Key, item.Value);
    }
}

private static IEnumerable<KeyValuePair<int,int>> Level(List<TreeNode> list, int? parentId, int lvl)
{
    return list
        .Where(x => x.ParentId == parentId)
        .SelectMany(x => 
            new[] { new KeyValuePair<int, int>(x.Id, lvl) }.Concat(Level(list, x.Id, lvl + 1))
        );
}


 类似资料:
  • 问题内容: 我在数据库中存储了一组依赖项。我正在寻找直接或间接依赖于当前对象的所有对象。由于对象可以依赖零个或多个其他对象,因此完全可以合理地认为对象1被对象9两次依赖(9依赖于4和5,这两个都依赖于1)。我想获取不依赖复制的所有依赖于当前对象的对象的列表。 如果存在循环,这将变得更加复杂。没有循环,一个人可以使用DISTINCT,尽管多次经过长链仅在末尾剔除它们仍然是一个问题。但是,对于循环,重

  • 问题内容: 此查询生成从1到4的数字。 但是,如果我对此进行修改, 它给 错误:“ z”处或附近的语法错误 我在这里做错了什么? 问题答案: 我认为这是因为RECURSIVE是WITH语句的修饰符,而不是常用表表达式的属性,因此您可以像这样使用它:

  • 问题内容: 我不是SQL专家,但是如果有人可以帮助我。 我使用递归CTE来获取如下值。 Child1 –> Parent 1 Parent1 –> Parent 2 Parent2 –> NULL 如果数据填充出错,那么我将遇到以下类似情况,因此CTE可能会进入无限递归循环并给出最大递归错误。由于数据量很大,因此我无法手动检查此 错误数据 。请让我知道是否有办法找到它。 Child1 –> Par

  • 问题内容: 我正在尝试执行我认为使用CTE进行递归比较困难的事情是SQL Server 2008。 在下面的示例中,您可以假设固定深度为3 …没有任何比这更低的深度了。在现实生活中,深度是“更深的”,但仍然是固定的。在示例中,我尝试将其简化一些。 我的输入数据如下。 我的CTE的输出应为下表。 如果我可以在输出中获得ID列,则可以肯定地可以映射到查找表中的名称。 我也乐于接受其他方法来完成此任务,

  • 我有一个scala类a,其中有一个方法。 还有一个B类

  • 问题内容: 我正在开发一个Web应用程序,该应用程序显然在iOS设备中存在问题。问题是我不拥有iOS设备,而是在Linux Ubuntu中进行开发。我正在寻找一种在Linux(尤其是浏览器)中仿真/模拟此OS的方法,但是还没有找到任何东西。 到目前为止,我发现的是iOS SDK的Simulator,但这是针对Mac的。还有一些Windows模拟器。有人做过吗? 问题答案: 我能想到的唯一解决方案是