我有一个表,我需要从视图中获取一些特定数据。这是包含一些示例数据的基表结构:
| UserID | ReportsToUserID | Org ID |
-------------------------------------
| 1 | NULL | 1 |
-------------------------------------
| 2 | 1 | 1 |
-------------------------------------
| 3 | 2 | 1 |
-------------------------------------
| 4 | 3 | 1 |
-------------------------------------
用户将输入报告,用户可以查看向其报告的用户以及向这些用户报告的任何用户的报告。向任何人报告的用户都可以看到他们组织中的所有内容根据上面的示例数据,用户1可以看到2,3,和2的报告。 4;用户2可以看到3& 4;用户3可以看到4的报告。
对于视图,我希望返回的数据如下:
| UserID | CanSeeUserID | OrgID |
--------------------------------------------
| 1 | 2 | 1 |
--------------------------------------------
| 1 | 3 | 1 |
--------------------------------------------
| 1 | 4 | 1 |
--------------------------------------------
| 2 | 3 | 1 |
--------------------------------------------
etc...
以下是我目前的代码,非常感谢任何帮助。
WITH CTEUsers (UserID, CanSeeUserID, OrgID)
AS
(
SELECT e.ID, e.ReportsToUserID, e.OrgID
FROM Users e WITH(NOLOCK)
WHERE COALESCE(ReportsToUserID,0) = 0 --ReportsToUserID can be NULL or 0
UNION ALL
SELECT e.ReportsToUserID, e.ID,e.OrgID
FROM Users e WITH(NOLOCK)
JOIN CTEUsers c
ON e.ID = c.UserID
)
SELECT * FROM CTEUsers
答案 0 :(得分:1)
我知道它并不漂亮,但我快速查看的唯一方法是在分层查询上运行光标。聪明的人几乎可以肯定得到比我更好的答案,但是周五下午,我要去酒吧了!
SET NOCOUNT ON;
DECLARE @Users TABLE
(
UserID int NOT NULL,
[Name] varchar(10),
ReportsToUserID int,
OrgID int
)
DECLARE @Output TABLE
(
UserID int,
CanSeeReportsFrom int
)
INSERT INTO @Users VALUES (1, 'Dan', NULL, 1)
INSERT INTO @Users VALUES (2, 'Tom', 1, 1)
INSERT INTO @Users VALUES (3, 'Dick', 2, 1)
INSERT INTO @Users VALUES (4, 'Harry', 3, 1)
DECLARE @UserID int
DECLARE csr CURSOR FAST_FORWARD FOR
SELECT COALESCE(UserID, 0)
FROM @Users
OPEN csr
FETCH NEXT FROM csr INTO @UserID
WHILE (@@FETCH_STATUS = 0)
BEGIN
;WITH CTEUsers
AS
(
SELECT @UserID AS CallingUserID,
e.UserID,
e.ReportsToUserID
FROM @Users e
WHERE COALESCE(e.ReportsToUserID, 0) = @UserID
UNION ALL
SELECT @UserID,
e.UserID,
e.ReportsToUserID
FROM @Users e INNER JOIN CTEUsers c ON e.ReportsToUserID = c.UserID
)
INSERT INTO @Output
SELECT CallingUserID, UserID FROM CTEUsers
FETCH NEXT FROM csr INTO @UserID
END
CLOSE csr
DEALLOCATE csr
SELECT * FROM @Output
答案 1 :(得分:1)
WITH reports (userid, orgid, [Level])
AS (SELECT e.userid,
e.orgid,
0 AS [Level]
FROM users e
WHERE Coalesce(reportstouserid, 0) = 0
UNION ALL
SELECT e.userid,
e.orgid,
[Level] + 1
FROM users AS e
INNER JOIN reports AS d
ON d.userid = e.reportstouserid)
-- Statement that executes the CTE
SELECT a.[UserID],
b.userid [CanSeeUserID],
a.[OrgID]
FROM reports a
JOIN reports b
ON a.[Level] < b.[Level]
答案 2 :(得分:1)
我使用以下内容创建一个Temp表,其中包含一些与您相似的数据:
IF OBJECT_ID('tempdb..#Stage1') IS NOT NULL DROP TABLE #Stage1;
GO
WITH CTEFillTemp AS (
SELECT 1 [UserId], NULL [ReportsToUserID], 1 [OrgId] UNION ALL
SELECT 2 [UserId], 1 [ReportsToUserID], 1 [OrgId] UNION ALL
SELECT 3 [UserId], 2 [ReportsToUserID], 1 [OrgId] UNION ALL
SELECT 4 [UserId], NULL [ReportsToUserID], 2 [OrgId] UNION ALL
SELECT 5 [UserId], 3 [ReportsToUserID], 1 [OrgId] UNION ALL
SELECT 6 [UserId], 4 [ReportsToUserID], 2 [OrgId] UNION ALL
SELECT 7 [UserId], 3 [ReportsToUserID], 1 [OrgId]
) SELECT * INTO #Stage1 FROM CTEFillTemp
GO
SELECT * FROM #Stage1
GO
然后我使用了以下查询:
WITH CTE (UserId, CanSeeUserId, OrgId, Level) AS (
SELECT #Stage1.ReportsToUserId, #Stage1.UserId, #Stage1.[OrgId], 0 [Level] FROM #Stage1
UNION ALL
SELECT #Stage1.ReportsToUserId, CTE.CanSeeUserId, CTE.[OrgId], [Level] + 1 FROM #Stage1
INNER JOIN CTE ON #Stage1.UserId = CTE.UserId AND #Stage1.[OrgId] = CTE.[OrgId]
)
SELECT *
FROM CTE
WHERE [UserId] IS NOT NULL
ORDER BY UserId, [Level]
这应该产生你想要的结果,但是因为它使用递归公用表表达式,它不是无限级别的可靠解决方案。 OPTION (MAXRECURSION 99)
虽然可以提供帮助。
答案 3 :(得分:0)
请检查以下查询是否符合您的目的。
Select A.UserID, B.UserID as 'CanSeeID',A.OrgID from
USERS A
LEFT OUTER JOIN USERS B
ON ( A.ReportstoUserId is NULL OR A.ReportstoUserId=0 )
OR A.UserId = B.ReportstoUserId