SQL - заполнение групповой таблицы - PullRequest
1 голос
/ 20 мая 2011

Учитывая следующие таблицы / отношения

enter image description here

РЕДАКТИРОВАТЬ: Что, если заполнено с использованием SQL ниже, должно вернуть это ....

enter image description here

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

Цель

Я пытаюсь заполнить 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).

Если бы «Housekeeping Supervisor» был связан с другой задачей, а других ролей не было, мне не нужно было бы создавать другую группу, так каконо уже было распознано.

О, я пытаюсь добиться этого с помощью SQL в SQL Server 2008.

Любые советы или подсказки приветствуются.

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);

1 Ответ

0 голосов
/ 21 мая 2011

Я не уверен, что прекрасно понимаю ваши вопросы, но, как предположили комментаторы, у вас, вероятно, есть проблема с вашей схемой.

С одной стороны, группа ролей - это роль, скрывающаяся под другим именем; единственное отличие, основанное на вашей схеме, состоит в том, что она не обязательно принадлежит отделу. Но опять же, вы можете сказать то же самое о ролях: даже в крупных компаниях часто есть пользователь / роль, которая подчиняется нескольким руководителям и, следовательно, принадлежит нескольким отделам.

Итак, на самом деле вы смотрите на групповую иерархию. Если вы абстрагируете вещи в будущем, вы будете счастливы иметь возможность назначить задачу нескольким ролям за один раз. Вы можете разумно сбросить роли и группы ролей в одну таблицу, роли, вместе с таблицей role2role, которая позволяет связать их друг с другом: некоторые роли назначают другие роли, но обратное не верно; некоторые роли принадлежат нескольким группам ролей; и группы ролей имеют несколько групп; это ориентированный граф, первичным ключом которого будет (ParentId, Id), оба из которых ссылаются на роли (Id).

Кроме того, ваша таблица RoleTask, по сути, уже отвечает на ваш запрос. Но вы все еще хотите новый под названием RoleGroup. И если я получу объяснения, которые вы дадите в комментариях к своему вопросу, добавление новой задачи и новой связанной роли автоматически приведет к новой группе ролей. Это инъективное свойство должно указывать на то, что задачи тоже являются ролями, скрывающимися и под другим именем.

Кроме того, обратите внимание, что некоторые задачи могут быть разложены на несколько отдельных задач, и что эти отдельные подзадачи могут быть частью нескольких больших задач. Это тоже ориентированный граф.

В любом случае, это означает, что вам следует рассмотреть возможность объединения всех этих таблиц вместе. Чтобы можно было легко добавлять внешние ключи, вы можете разделить их на три части, но если вы сделаете это, я бы предложил, чтобы задачи и RoleGroup были обрезаны до поля Id, которое является как первичным ключом, так и внешним ключ к ролям (Id).

К тому же, вы также можете посмотреть в таблицу Department и применить там ту же логику. Для этого может потребоваться несколько дополнительных деталей, например, ManagerId, но, в конце концов, он также играет роль под другим именем: его главная цель - объединить пользователей в группы, и, возможно, в некоторых случаях всем пользователям в отделе следует выполнить некоторые задачи. Он вписывается прямо в ориентированный граф, описанный выше.

Наконец, но не в последнюю очередь, возможно, стоит указать, что отдельные пользователи (которые не показаны на вашей диаграмме, но которые обязательно присутствуют в вашей схеме) также являются ролями сами по себе. Вполне может быть, что задача специально назначается человеку, а не роли или группе. Кроме того, вы никогда не знаете, когда менеджер хочет передать свои полномочия своему секретарю, потому что он в конце месяца в отпуске.

Теперь, возможно, вполне возможно справиться со всем этим беспорядком, используя множество таблиц и взаимосвязей между ними, как вы пытаетесь это сделать сейчас. Но вы также можете ввести две новые таблицы, например, Perm (как в разрешениях) и PermPerm (как в назначениях разрешений). И заставить отдельные узлы (то есть пользователя, отдела, роли, задачи) наследовать от Перми. Это позволит вам управлять всем графом разрешений из одной таблицы: PermPerm.

О, и если у вас есть час, подумайте о просмотре этого видео: ACL мертв . У него есть интересные идеи по управлению разрешениями:

...