【问题标题】:SQL - Populating Group TableSQL - 填充组表
【发布时间】:2011-05-20 17:10:27
【问题描述】:

鉴于以下表格/关系

编辑:如果使用下面的 SQL 填充应该返回这个....

SELECT     TOP (100) PERCENT dbo.Task.Name AS Expr1, dbo.Role.Name FROM dbo.Role INNER JOIN dbo.RoleTask ON dbo.Role.Id = dbo.RoleTask.RoleId INNER JOIN                       dbo.Task ON dbo.RoleTask.TaskId = dbo.Task.Id ORDER BY dbo.Task.Name, dbo.Role.Name

瞄准

我正在尝试使用 Role 和 Task 之间的多对多关系定义的角色组填充 RoleGroup(刚刚挂在那里的那个!),认识到有些可能已经在 RoleGroup 表中。

编辑:因此,鉴于上面的示例结果,这就是我需要在 RoleGroup 中看到的内容(自原始帖子以来我已经对此进行了修改,希望能更清楚地了解我的身份努力实现)...

GroupId      RoleId
1            Plumber
2            Gardener
2            Topiary Guru
3            Electrician
4            Cleaner
4            Housekeeping Supervisor
4            Toilet Cleaning Specialist  
5            Housekeeping Supervisor

结果说明

由于角色已与某些任务相关联,因此可以识别角色组。

在我的示例中,“清洁工、家政主管和厕所清洁专家”都与“厕所清洁”任务相关联。因此,我可以说那是一个群体,并且想要提取这些信息。

同样,“家政主管”已与“厕所检查”任务相关联;并且没有其他角色。这意味着应该提取另一个新组(2 - Housekeeping Supervisor)。

如果“家政主管”与另一个任务相关联,并且没有其他角色,我不需要创建另一个组,因为它已经被识别了。

哦,我正在尝试使用 SQL Server 2008 中的 SQL 来实现这一点。

任何提示或提示表示赞赏。

SQL

USE TestDatabase
GO

CREATE TABLE [dbo].[Task](
    [Id] [int] NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_Type] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Department](
    [Id] [int] NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
 CONSTRAINT [PK_Department] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[RoleGroup](
    [Id] [int] NOT NULL,
    [RoleId] [int] NOT NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[Role](
    [Id] [int] NOT NULL,
    [Name] [nvarchar](50) NOT NULL,
    [DepartmentId] [int] NOT NULL,
 CONSTRAINT [PK_Role] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[RoleTask](
    [RoleId] [int] NOT NULL,
    [TaskId] [int] NOT NULL,
 CONSTRAINT [PK_RoleTask] PRIMARY KEY CLUSTERED 
(
    [RoleId] ASC,
    [TaskId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
/****** Object:  ForeignKey [FK_Role_Department]    Script Date: 05/20/2011 17:56:49 ******/
ALTER TABLE [dbo].[Role]  WITH CHECK ADD  CONSTRAINT [FK_Role_Department] FOREIGN KEY([DepartmentId])
REFERENCES [dbo].[Department] ([Id])
GO
ALTER TABLE [dbo].[Role] CHECK CONSTRAINT [FK_Role_Department]
GO

/****** Object:  ForeignKey [FK_RoleTask_Role]    Script Date: 05/20/2011 17:56:49 ******/
ALTER TABLE [dbo].[RoleTask]  WITH CHECK ADD  CONSTRAINT [FK_RoleTask_Role] FOREIGN KEY([RoleId])
REFERENCES [dbo].[Role] ([Id])
GO
ALTER TABLE [dbo].[RoleTask] CHECK CONSTRAINT [FK_RoleTask_Role]
GO

/****** Object:  ForeignKey [FK_RoleTask_Task]    Script Date: 05/20/2011 17:56:49 ******/
ALTER TABLE [dbo].[RoleTask]  WITH CHECK ADD  CONSTRAINT [FK_RoleTask_Task] FOREIGN KEY([TaskId])
REFERENCES [dbo].[Task] ([Id])
GO
ALTER TABLE [dbo].[RoleTask] CHECK CONSTRAINT [FK_RoleTask_Task]
GO
/** DATA **/

INSERT INTO [Department] ([Id], [Name]) VALUES (1, 'Housekeeping');
INSERT INTO [Department] ([Id], [Name]) VALUES (2, 'Security');
INSERT INTO [Department] ([Id], [Name]) VALUES (3, 'External Maintenance');
INSERT INTO [Department] ([Id], [Name]) VALUES (4, 'Internal Maintenance');

INSERT INTO [Role] ([Id], [Name], [DepartmentId]) VALUES (1, 'Cleaner', 1);
INSERT INTO [Role] ([Id], [Name], [DepartmentId]) VALUES (2, 'Housekeeping Supervisor', 1);
INSERT INTO [Role] ([Id], [Name], [DepartmentId]) VALUES (3, 'Toilet Cleaning Specialist', 1);
INSERT INTO [Role] ([Id], [Name], [DepartmentId]) VALUES (4, 'Security Guard', 2);
INSERT INTO [Role] ([Id], [Name], [DepartmentId]) VALUES (5, 'Electrician', 4);
INSERT INTO [Role] ([Id], [Name], [DepartmentId]) VALUES (6, 'Plumber', 4);
INSERT INTO [Role] ([Id], [Name], [DepartmentId]) VALUES (7, 'Gardener', 3);
INSERT INTO [Role] ([Id], [Name], [DepartmentId]) VALUES (8, 'Topiary Guru', 3);

INSERT INTO [Task] ([Id], [Name]) VALUES (1, 'Toilet Clean');
INSERT INTO [Task] ([Id], [Name]) VALUES (2, 'Light Out');
INSERT INTO [Task] ([Id], [Name]) VALUES (3, 'Blocked Sink');
INSERT INTO [Task] ([Id], [Name]) VALUES (4, 'Toilet Inspection');
INSERT INTO [Task] ([Id], [Name]) VALUES (5, 'Leaky Tap');
INSERT INTO [Task] ([Id], [Name]) VALUES (6, 'Bush too bushy');
INSERT INTO [Task] ([Id], [Name]) VALUES (7, 'Mop Floor');

INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (1, 1);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (2, 1);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (3, 1);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (5, 2);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (6, 3);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (2, 4);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (6, 5);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (7, 6);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (8, 6);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (1, 7);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (2, 7);
INSERT INTO [RoleTask] ([RoleId], [TaskId]) VALUES (3, 7);

【问题讨论】:

  • 我已经盯着这个了,但我就是不知道你想做什么。给定您的示例数据,RoleGroup 的内容会是什么样子?
  • @Philip Kelley:谢谢。我编辑了这篇文章以突出我所追求的。如前所述,我需要能够一遍又一遍地运行例程来添加新组,但不能重复现有条目。如果仍然不清楚,请告诉我,我会尽力解释得更好。
  • RoleGroup 表的用途是什么,它与Role 表有何不同?
  • @Brent D:它最终将包含一组角色。在我给出的示例中,第 1 组由 [清洁工、家政主管和厕所清洁专家] 组成,第 2 组只是 [家政主管] 等。角色只是所有可用的个人角色。
  • 我只是不够聪明,无法理解这一点。目前我的理解是 RoleTask 表已经正是你想要的。

标签: sql tsql sql-server-2008 data-warehouse dimensions


【解决方案1】:

我不确定我是否完全理解了您的问题,但正如评论者所建议的那样,您的架构可能存在问题。

一方面,角色组是隐藏在不同名称下的角色;基于您的架构的唯一区别是它不一定属于一个部门。但话又说回来,您也可以对角色说同样的话:即使在大型公司中,也经常有一个用户/角色向多个老板汇报,因此属于多个部门。

所以您真正看到的是组层次结构。如果您将事情抽象化,您会很高兴能够一次性将一项任务分配给多个角色。您可以将角色和角色组合理地转储到一个表中,角色,以及一个允许将它们相互关联的 role2role 表:一些角色分配其他角色,但反之亦然;一些角色属于多个角色组;并且角色组有多个组;它是一个有向图,其主键为 (ParentId, Id),两者都引用 Roles(Id)。

此外,您的 RoleTask 表在所有意图和目的上都已经回答了您的查询。但是您仍然需要一个名为 RoleGroup 的新角色。如果我得到你在问题 cmets 中给出的解释,添加一个新任务和一个新的关联角色会自动导致一个新的角色组。这个单射属性应该暗示任务也是隐藏在不同名称下的角色。

此外,请注意,某些任务可以分解为多个单独的任务,并且这些单独的子任务可能是多个更大任务的一部分。这也是一个有向图。

无论如何,这意味着您应该考虑将所有这些表合并在一起。为了能够轻松添加外键,您可能希望将它们分成三部分,但如果您这样做,我建议将 Tasks 和 RoleGroup 修剪为 Id 字段,它既是主键也是外键Roles(Id) 的键。

出于同样的原因,您可能还想查看 Department 表并在那里应用相同的逻辑。它可能需要一些额外的细节,例如一个ManagerId,但归根结底,它也是一个不同名称的角色:它的主要目的是将用户分组在一起,也许一个部门内的所有用户在某些情况下都应该得到一些任务。它正好适合上面描述的有向图。

最后但并非最不重要的一点是,可能值得指出的是,单个用户(未显示在您的图表中,但肯定存在于您的架构中)本身也是角色。很可能任务是专门分配给个人而不是角色或一组。另外,你永远不知道经理什么时候想将他的权限委派给他的秘书,因为他在月底休假。

现在,可以说,使用大量表和它们之间的关系来管理整个混乱当然是可能的,就像您现在尝试做的那样。但是您也可以引入两个新表,例如 Perm(如权限)和 PermPerm(如权限分配)。并使各个节点(即用户、部门、角色、任务)继承自 Perm。这样做将允许您从单个表管理整个权限图:PermPerm。

哦,如果您有一个小时,请考虑观看此视频:The ACL is dead。它对权限管理有有趣的见解:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 2018-06-02
    • 2020-08-23
    • 2017-01-07
    • 1970-01-01
    • 2021-09-22
    • 2012-08-13
    相关资源
    最近更新 更多