我必须创建一个查询,它将返回用户和他们有权访问的应用程序模块。除了用户和模块列表外,如果该用户无法访问任何模块,则查询也应返回。
'ApplicationUsers'表是这样的:
CREATE TABLE #ApplicationUsers
(
userId INT,
UserName VARCHAR(50)
)
INSERT INTO #ApplicationUsers VALUES
(1, 'Daniel'), (2,'Martin'), (3, 'Brandon'), (4, 'Doug')
'ApplicationModule'表是这样的:
CREATE TABLE #ApplicationModules
(
moduleId INT,
moduleName VARCHAR(50)
)
INSERT INTO #ApplicationModules VALUES
(1, 'Sales'), (2, 'Production'), (3, 'Marketing')
这是我们在'ModuleAccess'表中为用户存储模块访问的方式:
CREATE TABLE #ModuleAccess
(
Id INT,
userId INT,
moduleId INT
)
INSERT INTO #ModuleAccess VALUES
(1, 1, 1), (2, 1, 3), (3, 2, 1), (4, 2, 2), (5, 3, 2)
在上面的例子中,'Daniel'只能访问'Sales'和'Marketing','Martin'可以访问'Sales'和'Production'等等。所以所需的输出是:
CREATE TABLE #ExampleOutput
(
[userName] VARCHAR(50),
[Sales] VARCHAR(5),
[Production] VARCHAR(5),
[Marketing] VARCHAR(5)
)
INSERT INTO #ExampleOutput VALUES
('Daniel', 'true', 'false', 'true'),
('Martin', 'true', 'true', 'false'),
('Brandon', 'false', 'true', 'false'),
('Doug', 'false', 'false', 'false')
SELECT * FROM #ExampleOutput
我使用了数据透视查询,但它有一些限制(可能是我在制作错误)。首先,pivot列是静态的,而我需要动态列名(Application Modules)。其次,我需要包含所有具有访问权限的模块的所有用户,或者无法访问我无法访问的模块。有人可以写一个示例查询来帮助我如何做到这一点吗?
答案 0 :(得分:0)
如果您坚持使用问题中所述的表格设计,这将有效。
(SELECT username, am.moduleName AS Module, CAST(0 AS BIT) AS HasAccess
FROM #ApplicationUsers AS au INNER JOIN #ApplicationModules AS am ON 1 = 1
EXCEPT
SELECT username, am.moduleName AS Module, CAST(0 AS BIT) AS HasAccess
FROM #ApplicationUsers AS au INNER JOIN #ModuleAccess AS ma ON ma.userId = au.userId INNER JOIN #ApplicationModules AS am ON am.moduleId = ma.moduleId)
UNION
SELECT username, am.moduleName AS Module, CAST(1 AS BIT) AS HasAccess
FROM #ApplicationUsers AS au INNER JOIN #ModuleAccess AS ma ON ma.userId = au.userId INNER JOIN #ApplicationModules AS am ON am.moduleId = ma.moduleId
ORDER BY 1, 2
虽然有笛卡尔加入" 1 = 1"不太好的解决方案。如果你能够修改ModuleAccess表并包含一个" HasAccess BIT NOT NULL DEFAULT(0)"列,并让应用程序包含新用户的所有模块。如果用户没有访问权限,则将新列设置为零,如果他们有访问权限,则将其设置为1。
答案 1 :(得分:0)
如果有人有类似的要求,这是工作查询:
DECLARE @DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)
SELECT @ColumnName = ISNULL(@ColumnName + ',', '') + QUOTENAME([moduleName])
FROM (
SELECT DISTINCT [moduleName]
FROM #ApplicationModules
) AS ApplicationModules
SET @DynamicPivotQuery = '
SELECT * FROM
(
SELECT D.[moduleId], D.[moduleName], U.[UserName] AS [User] FROM
#ApplicationUsers U
LEFT OUTER JOIN #ModuleAccess DA
ON U.[userId] = DA.[userId]
LEFT OUTER JOIN #ApplicationModules D
ON D.[moduleId] = DA.[moduleId]
) A
pivot (MIN(moduleId)for [moduleName] in (' + @ColumnName + ')) as [moduleIdId]
'
EXEC sp_executesql @DynamicPivotQuery
DROP TABLE #ApplicationUsers
DROP TABLE #ModuleAccess
DROP TABLE #ApplicationModules