Я согласен с другими, что ваш дизайн не идеален, и учитывая тот факт, что он может измениться, согласно вашему комментарию, человек не слишком мотивирован, чтобы найти действительно увлекательное решение длятекущая ситуация.
Тем не менее, у вас может быть тот, который, по крайней мере, работает правильно (я думаю) и соответствует ситуации.Вот что я придумал:
;
WITH
UserDepartment ([User], Department) AS (
SELECT 'user1', 'IT,HR,House Keeping' UNION ALL
SELECT 'user2', 'HR,House Keeping' UNION ALL
SELECT 'user3', 'IT,Finance,HR,Maintainance' UNION ALL
SELECT 'user4', 'Finance,HR,House Keeping' UNION ALL
SELECT 'user5', 'IT,HR,Finance'
),
Filter (FilterValue) AS (
SELECT 'IT' UNION ALL
SELECT 'Finance' UNION ALL
SELECT 'HR'
),
CSVSplit AS (
SELECT
ud.*,
--x.node.value('.', 'varchar(max)')
x.Value AS aDepartment
FROM UserDepartment ud
CROSS APPLY (SELECT * FROM dbo.Split(',', ud.Department)) x
)
SELECT
c.[User],
c.Department
FROM CSVSplit c
INNER JOIN Filter f ON c.aDepartment = f.FilterValue
GROUP BY
c.[User],
c.Department
HAVING
COUNT(*) = (SELECT COUNT(*) FROM Filter)
Первые два CTE - это просто примеры таблиц, остальная часть запроса - это собственно решение.
* CTE CSVSplit
используетSplit
функция , которая разбивает список через запятую на набор элементов и возвращает их в виде таблицы.Весь CTE превращает набор строк в форме
----- ---------------------------
user1 department1,department2,...
... ...
в следующее:
----- -----------
user1 department1
user1 department2
... ...
Основной SELECT объединяет нормализованный набор строк с таблицей фильтров и выбирает строки, в которых числосоответствует точно равно количеству элементов в таблице фильтров. (Примечание: это означает, что в UserDepartment.Department
нет идентичных имен) .