【问题标题】:SQL for each row do somethingSQL 为每一行做一些事情
【发布时间】:2018-06-18 12:06:45
【问题描述】:

我有一个 SQL 查询,用于查找指定人员有权访问的“部门”。

有些部门是其他部门的子部门,因此当此人有权访问某个部门时,他也可以访问他的所有子部门。

之所以可行,是因为在部门表中,每个部门都有一个名称和 ID 以及一个“fatherID”,它指定哪个部门是他的父部门。

但这也有可能嵌套得更深,我发现无法显示低于 1 级子部门的所有部门的名称。

SELECT B.DepartmentDesc FROM  CompanyDepartmentPermission A 
INNER JOIN CompanyDepartment] B 
ON A.DepartmentID=B.DepartmentID 
OR A.DepartmentID=B.FatherDepartmentID 
WHERE A.PEmplID = 68

这是可能的。我得到了部门和他所有子部门的所有名字:

但在这种情况下,我得到了每个子部门,除了嵌套级别更低。

我的目标是能够递归地显示所有嵌套的子部门。 我只需要在 1 个查询中执行此操作。由于我非常缺乏经验并且对嵌套查询没有太多洞察力,我还没有找到解决这个问题的方法。我希望有人能给我一个正确的方向。

PS:图片来自我制作的 C# 程序,我让它工作的地方,这只是为了澄清它的外观。我希望我能解释我想要什么。否则请告诉我,我会尝试改写这个:)

编辑: 这是两个表的结构。感谢赤野指出

解决方案: 可悲的是,这里没有一个回答对我有帮助,而是在 SO 上有一个类似的问题。 WITH UNION 语句对我帮助很大。这是我的问题的有效查询。

WITH DepartmentHirarchy AS
(
SELECT B.DepartmentID,DepartmentDesc,FatherDepartmentID, DepartmentResponsiblePEmplID
FROM CompanyDepartment AS B
INNER JOIN CompanyDepartmentPermission AS A ON A.DepartmentID=B.DepartmentID
WHERE A.PEmplID= 34 OR DepartmentResponsiblePEmplID = 34
UNION ALL
SELECT  nextLevel.DepartmentID,nextLevel.DepartmentDesc,nextLevel.FatherDepartmentID, nextLevel.DepartmentResponsiblePEmplID
FROM DepartmentHirarchy AS recCall
INNER JOIN CompanyDepartment AS nextLevel ON nextLevel.FatherDepartmentID=recCall.DepartmentID
)
SELECT * FROM DepartmentHirarchy
ORDER BY FatherDepartmentID,DepartmentID
GO

【问题讨论】:

  • 从数据库中选择所有部门并用C#组织它们
  • @selami 我很遗憾不能使用 c#,我必须使用 1 个查询。这是我的老板给我的一个特定用途的任务
  • 那是糟糕的设计。在不知道嵌套查询需要多“深”的情况下,使用纯 sql 完成此操作的机会很小。你有数据库模式吗?可能还有另一种更方便的方法。
  • @akaino 我会更新问题
  • @akaino 据我所知,我的老板希望这个单一的查询能够复制粘贴以供某些用途。他做了几年的程序员,所以我想当他要求时可以这样做:)

标签: sql sql-server


【解决方案1】:

对于父/子树层次结构,请尝试以下 SQL 代码。

我假设,您的表名是 Departments。您可以在以下 SQL 中更改表名。

我使用 SQL Server。

WITH RELATION (DepartmentID, FatherDepartmentID, DepartmentDesc, [Level], [Order])
AS
(
    SELECT DepartmentID, FatherDepartmentID, DepartmentDesc, 0, CAST(DepartmentID AS VARCHAR(200))
    FROM Departments
    WHERE FatherDepartmentID IS NULL
    UNION ALL
    SELECT P.DepartmentID, P.FatherDepartmentID, P.DepartmentDesc, R.[Level]+1, CAST(R.[Order] + '_' + CAST(p.DepartmentID AS VARCHAR(200)) AS VARCHAR(200))  
    FROM Departments P
    JOIN RELATION R ON P.FatherDepartmentID = R.DepartmentID
)
SELECT RIGHT('----------', ([Level]*3)) + DepartmentDesc  
FROM RELATION R
JOIN CompanyDepartment D ON D.DepartmentID = R.DepartmentID 
WHERE PEmplID= 68
ORDER BY R.[ORDER]

【讨论】:

  • 我只是想了解您的查询,但我无法理解的一件事是另一张桌子在哪里?不知何故,权限表不在查询中,因此作为权限表一部分的“PEmplID”不起作用。
  • 这只是您在第一个示例查询中所做的另一个联接。这是遍历未知深度的自引用表的标准方法。你绝对应该追求这个解决方案。其他解决方案都不会到达树的底部。这个会,不管它有多深。
  • @Nick.McDermaid 是的,看起来不错,但我不知道第二个表的引用位置。他引用了部门表 2 次,但没有引用权限表。 ://
  • 看到底部的FROM RELATION 行了吗?你像这样加入:FROM RELATION INNER JOIN CompanyDepartmentPermission ON你的加入条件
  • @MansNotHot 在您的问题中,“CompanyDepartment] B ”中有一个额外的 ']' 字符是否有两个表?还是只有一张桌子?
【解决方案2】:

您似乎想要进行层次结构搜索。 如果您的服务器支持使用层次结构数据类型(如果不支持,如果您打算使用大量层次结构搜索,则可能需要考虑它)您可以尝试使用 isDescendantOf 方法。

例子

DECLARE @parent hierarchyid
SELECT @parent = B.DepartmentDesc
FROM CompanyDepartment B 
Where B.DepartmentDesc = 'Name your deparment'

SELECT *  
FROM CompanyDepartment 
WHERE DepartmentDesc.IsDescendantOf(@parent) = 1 ; 

【讨论】:

  • This on;y 适用于具有层次结构数据类型的 SQL Server。您在这里做了一些假设。
  • @Nick.McDermaid ,你是对的,我改写了答案以使其更清楚。
猜你喜欢
  • 2015-10-20
  • 2015-07-17
  • 1970-01-01
  • 1970-01-01
  • 2019-04-23
  • 1970-01-01
  • 1970-01-01
  • 2015-02-24
  • 1970-01-01
相关资源
最近更新 更多