В рамках этой проблемы у меня есть 3 сущности:
User
Position
License
Тогда у меня есть две реляционные (многие-ко-многим) таблицы:
PositionLicense
- этот соединяет Position
с License
т.е. какие лицензии требуются для конкретной должности
UserLicense
- этот соединяет User
с License
т.е. какие лицензии имеет конкретный пользователь. Но с дополнительной сложностью: пользовательские лицензии имеют срок действия (ValidFrom
и ValidTo
)
проблема
Это входные переменные:
UserID
, который идентифицирует конкретный User
RangeFrom
определяет нижний предел диапазона дат
RangeTo
определяет верхний предел диапазона дат
Что мне нужно, чтобы получить ? Для конкретного пользователя (и диапазона дат) мне нужно получить список должностей, над которыми этот конкретный пользователь может работать. Проблема в том, что пользователь должен иметь как минимум все лицензии, необходимые для каждой соответствующей позиции.
У меня огромные проблемы при написании SQL-запроса для получения этого списка.
Если это вообще возможно, я хотел бы сделать это с помощью одного SQL-запроса (конечно, может иметь дополнительные CTE). Если вы можете убедить меня в том, что выполнение нескольких запросов было бы более эффективным, я готов выслушать.
Некоторые работоспособные данные
Скопируйте и запустите этот скрипт. 3 пользователя, 3 должности, 6 лицензий. Марк и Джон должны иметь матч, но не Джейн.
create table [User] (
UserID int identity not null
primary key,
Name nvarchar(100) not null
)
go
create table Position (
PositionID int identity not null
primary key,
Name nvarchar(100) not null
)
go
create table License (
LicenseID int identity not null
primary key,
Name nvarchar(100) not null
)
go
create table UserLicense (
UserID int not null
references [User](UserID),
LicenseID int not null
references License(LicenseID),
ValidFrom date not null,
ValidTo date not null,
check (ValidFrom < ValidTo),
primary key (UserID, LicenseID)
)
go
create table PositionLicense (
PositionID int not null
references Position(PositionID),
LicenseID int not null
references License(LicenseID),
primary key (PositionID, LicenseID)
)
go
insert [User] (Name) values ('Mark the mechanic');
insert [User] (Name) values ('John the pilot');
insert [User] (Name) values ('Jane only has arts PhD but not medical.');
insert Position (Name) values ('Mechanic');
insert Position (Name) values ('Pilot');
insert Position (Name) values ('Doctor');
insert License (Name) values ('Mecha');
insert License (Name) values ('Flying');
insert License (Name) values ('Medicine');
insert License (Name) values ('PhD');
insert License (Name) values ('Phycho');
insert License (Name) values ('Arts');
insert PositionLicense (PositionID, LicenseID) values (1, 1);
insert PositionLicense (PositionID, LicenseID) values (2, 2);
insert PositionLicense (PositionID, LicenseID) values (2, 5);
insert PositionLicense (PositionID, LicenseID) values (3, 3);
insert PositionLicense (PositionID, LicenseID) values (3, 4);
insert UserLicense (UserID, LicenseID, ValidFrom, ValidTo) values (1, 1, '20110101', '20120101');
insert UserLicense (UserID, LicenseID, ValidFrom, ValidTo) values (2, 2, '20110101', '20120101');
insert UserLicense (UserID, LicenseID, ValidFrom, ValidTo) values (2, 5, '20110101', '20120101');
insert UserLicense (UserID, LicenseID, ValidFrom, ValidTo) values (3, 4, '20110101', '20120101');
insert UserLicense (UserID, LicenseID, ValidFrom, ValidTo) values (3, 6, '20110101', '20120101');
Результирующее решение
Я настроил полученное решение на основе принятого ответа, который обеспечивает наиболее упрощенное решение этой проблемы. Если вы хотите поиграть с запросом, просто нажмите edit / clone (вне зависимости от того, вошли вы в систему или нет). Что можно изменить:
- три переменные:
- две переменные для установки диапазона дат (
@From
и @To
)
- идентификатор пользователя (
@User
)
- вы можете переключать закомментированный код в первом CTE, чтобы переключать код между полностью перекрывающимися пользовательскими лицензиями или частично перекрывающимися.