sql递归cte在视图中不能正常工作
Posted
技术标签:
【中文标题】sql递归cte在视图中不能正常工作【英文标题】:sql recursive cte in view not work fine 【发布时间】:2016-06-17 11:18:51 【问题描述】:我做了一个 CTE 查询,它可以在存储过程中正常工作,并且当我在查询编辑器中执行时(使用 where 语句)
但是当我尝试创建与 View 相同的视图时(没有 where 语句)。 并使用 where 语句执行此操作,我得到的数据不是递归的。 我没有看到错误。
这是 SP 中的查询和查询编辑器,可以正常工作。 (SP中的Guid作为参数)
WITH recursiveTable(ParentApplicationRoleId, ChildApplicationRoleId)
AS
(
SELECT ParentApplicationRoleId, ChildApplicationRoleId
FROM ApplicationRoleParentChild
WHERE ParentApplicationRoleId = '69BCC94B-2884-4270-B39E-A09669C1D658'
UNION ALL
SELECT ApplicationRoleParentChild.ParentApplicationRoleId, ApplicationRoleParentChild.ChildApplicationRoleId
FROM ApplicationRoleParentChild
INNER JOIN recursiveTable ON ApplicationRoleParentChild.ParentApplicationRoleId = recursiveTable.ChildApplicationRoleId
)
/* Get all Childelements (from recursive Table) and add the ParentRoleId to this List */
SELECT ApplicationRole.Name AS RoleName
FROM recursiveTable
INNER JOIN ApplicationRole ON ApplicationRole.ApplicationRoleId = recursiveTable.ChildApplicationRoleId
UNION
SELECT Name AS RoleName FROM ApplicationRole WHERE ApplicationRoleId = '69BCC94B-2884-4270-B39E-A09669C1D658'
OPTION(MAXRECURSION 32767)
结果我得到Result Image
视图需要所有 ApplicationRoles(包含所有子角色)且未经过滤,因为我将在调用视图时使用过滤器。
如何在没有 where 语句的情况下更改 CTE?
我以这个为例。但它只返回“管理员”的直接子元素 我也从 Childs 中搜索 Child。
WITH recursiveTable(ParentApplicationRoleId, ChildApplicationRoleId)
AS
(
SELECT ParentApplicationRoleId, ChildApplicationRoleId
FROM ApplicationRoleParentChild
UNION ALL
SELECT ApplicationRoleParentChild.ParentApplicationRoleId, ApplicationRoleParentChild.ChildApplicationRoleId
FROM ApplicationRoleParentChild
INNER JOIN recursiveTable ON ApplicationRoleParentChild.ParentApplicationRoleId = recursiveTable.ChildApplicationRoleId
)
/* Get all Childelements (from recursive Table) and add the ParentRoleId to this List */
SELECT ApplicationRole.Name AS ChildRoleName, Parent.Name AS ParentRoleName
FROM recursiveTable
INNER JOIN ApplicationRole ON ApplicationRole.ApplicationRoleId = recursiveTable.ChildApplicationRoleId
INNER JOIN ApplicationRole as Parent ON Parent.ApplicationRoleId = recursiveTable.ParentApplicationRoleId
/*The Query-Filter when i call the View: Like SELECT * FROM View WHERE Parent.Name = 'Administrator'
Expected Returns: Role1-10, Departement1-3 and Administrator
Current Returns: Only direct Childs (Role2,7,8, Departement1,3)
Departement2 is Child of Departement1
And some other Roles are in one of the Departements or roles
*/
表: ApplicationRole(所有角色) ApplicationRoleParentChild(所有父子关系)(具有 FK 父和 FK 子角色)
我希望有人可以帮助我。
谢谢
【问题讨论】:
WHERE ParentApplicationRoleId is NULL
?第一个选择 - ***,第二个选择 - 树展开。
是的,使用 cte 是正确的 - 定义***的 where 子句
【参考方案1】:
yor where
子句过滤所有记录。和更深的记录没有直接的父管理员。
要按它进行过滤,您可以将***记录名称存储为 cte 中的列
WITH recursiveTable(ParentApplicationRoleId, ChildApplicationRoleId, TopLevelName)
AS
(
SELECT ParentApplicationRoleId, ChildApplicationRoleId, Name
FROM ApplicationRoleParentChild
UNION ALL
SELECT ApplicationRoleParentChild.ParentApplicationRoleId, ApplicationRoleParentChild.ChildApplicationRoleId
, recursiveTable.TopLevelName
FROM ApplicationRoleParentChild
INNER JOIN recursiveTable ON ApplicationRoleParentChild.ParentApplicationRoleId = recursiveTable.ChildApplicationRoleId
)
或者你甚至可以建立孩子的完整路径
WITH recursiveTable(ParentApplicationRoleId, ChildApplicationRoleId, TopLevelName)
AS
(
SELECT ParentApplicationRoleId, ChildApplicationRoleId, cast(Name as varchar(1000))
FROM ApplicationRoleParentChild
UNION ALL
SELECT ApplicationRoleParentChild.ParentApplicationRoleId, ApplicationRoleParentChild.ChildApplicationRoleId
, left(recursiveTable.TopLevelName + '/' + name, 1000)
FROM ApplicationRoleParentChild
INNER JOIN recursiveTable ON ApplicationRoleParentChild.ParentApplicationRoleId = recursiveTable.ChildApplicationRoleId
)
然后像where Parent.TopLevelName like '%Administrator%'
一样过滤
更新
如通知
Ivan Starostin 在他的评论中
如果您不想将每条记录的所有层次结构组合作为***。
您必须为 cte 中的第一个选择添加 where
子句以定义***节点。
类似ParentApplicationRoleId is NULL
或ParentApplicationRoleId = ''
【讨论】:
以上是关于sql递归cte在视图中不能正常工作的主要内容,如果未能解决你的问题,请参考以下文章
将 PostgreSQL 递归 CTE 转换为 SQL Server