Изначально я пытался создать VIEW с этими UNION, но это не сработало из-за различий в логике в каждом UNION и разных требований к параметрам, поэтому я подумал, что функция может решить эту проблему?Если бы я создал функцию, которая принимала за параметр @travellerid, и возвращал список аранжировщиков, основанных на бизнес-правилах, было бы это идеальным / быстрым решением?
Вы думаете, процедурный / OOпрограммирование, но SQL основан на SET.
Функция будет работать, но будет гарантировать, что индекс не может быть использован при использовании функции для критериев принятия решения / и т. д.Нематериализованный вид только немного лучше;в SQL Server есть возможность использовать индексированное представление (материализованное представление AKA), но они общеизвестно ограничены.Он идет вразрез с концепциями модульного программирования, но SQL работает тем лучше, чем меньше вы пытаетесь его модульно использовать и использовать только то, что вам действительно нужно.
Я переписал ваш запрос, но заметил, что на столбец dv.preferred ссылаютсяво внешнем запросе, но не присутствует во внутреннем.Поскольку dv
является конгломератом различных таблиц и логики, возвращаемое значение id
не имеет никакого реального значения вне внутреннего запроса, потому что вам необходимо знать, из какой таблицы получено значение.Тем не менее, вот оно:
SELECT t.id, t.firstname, t.lastname, ti.name AS title /*, dv.preferred */
FROM TRAVELLER t
JOIN title ti ON t.titleid = ti.id
WHERE (EXISTS(SELECT NULL -- Get Preferred Arrangers linked to Department Groups
FROM departmentGroup dg
JOIN department_departmentGroup ddg ON ddg.departmentGroupId = dg.id
AND ddg.departmentid = @departmentid
WHERE dg.arrangerid = t.id)
OR EXISTS(SELECT NULL -- Get Preferred Arrangers linked to Cost Centre Groups
FROM costCentreGroup cg
JOIN costcentre_costCentreGroup ccg ON ccg.costCentreGroupId = cg.id
AND ccg.costcentreid = @costcentreid
WHERE cg.arrangerid = t.id)
OR EXISTS(SELECT NULL -- If Cost Centre Group has a linked department and this department matches the travel arrangers department then return these travel arrangers as well
FROM costCentreGroup cg1
JOIN costcentre_costCentreGroup ccg1 ON ccg1.costCentreGroupId = cg1.id
AND ccg1.costcentreid = @costcentreid
JOIN traveller t3 ON t3.departmentid = cg1.departmentid
AND t3.accesslevelid > 1
WHERE t3.id = t.id)
OR EXISTS(SELECT NULL -- Get Direct linked travel arrangers
FROM travelarranger_traveller t1
WHERE t1.travellerid = @travellerid
AND t1.travelarrangerid = t.id)
OR EXISTS(SELECT NULL -- Get Cost Centre linked arrangers
FROM travelArranger_costcentre tc
WHERE tc.costcentreid = @costcentreid
AND tc.travelarrangerid = t.id)
OR EXISTS(SELECT NULL -- Get Department linked arrangers
FROM travelArranger_department td
WHERE td.departmentid = @departmentid
AND td.travelarrangerid = t.id)
OR EXISTS(SELECT NULL -- Get Company flagged arrangers
FROM traveller t2
JOIN company c ON t2.companyid = c.id
AND t2.accesslevelid > 1
WHERE ( (c.allowTravelArrangerDepartmentAccess = 1 AND t2.departmentid = @departmentid)
OR (c.allowTravelArrangerCostCentreAccess = 1 AND t2.costcentreid = @costcentreid))
AND t2.id = t.id))
AND t.accessLevelid > 1 -- arranger or manager
AND t.isenabled = 1
ORDER BY /*dv.preferred DESC,*/ t.lastname, t.firstname;
Использование подзапроса (IN, EXISTS) устранит проблему с дубликатами, возникающую при использовании объединений, если к родительскому элементу подключено более одной дочерней записи.