我有一個關於重用表數據的問題,但是在這種情況下視圖將不起作用,因爲我有一個需要傳入的參數。基本上這部分系統需要將travellerid
發送到過程,爲特定旅客返回的安排者名單。有大約7個業務規則用於確定哪些編排器可以返回並且它們是互斥的,所以爲了適應這些可選規則,我在派生查詢中使用了一系列UNION。這是行之有效的,而且在一個相當大的數據庫中性能似乎很好,但是我需要在系統的另外四個部分重用這些規則(UNION)。我應該使用T-SQL函數,查看還是存儲過程?
我最初試圖用這些UNION創建一個VIEW,但由於每個UNION的邏輯不同和參數的不同需求,所以我在想也許一個函數可以解決這個問題?如果我創建了一個將@travellerid
作爲參數並根據業務規則返回arrangerid
列表的函數,這是否是理想的/快速的解決方案?我目前在外部查詢中使用UNION ALL和DISTINCT,因爲這比使用UNION來處理數據的唯一性要快得多。
當前程序下面的業務規則(SQL Server 2008中):
CREATE PROCEDURE [dbo].[getArrangersForTraveller]
@travellerid int
AS
DECLARE @costcentreid int
DECLARE @departmentid int
-- Shorthand the traveller costcentre and department for use in queries below
SET @costcentreid = (SELECT costcentreid FROM traveller WHERE id = @travellerid)
SET @departmentid = (SELECT departmentid FROM traveller WHERE id = @travellerid)
SELECT DISTINCT t.id, t.firstname, t.lastname, ti.name AS title, dv.preferred
FROM traveller t
INNER JOIN title ti ON t.titleid = ti.id
INNER JOIN
(
-- Get Preferred Arrangers linked to Department Groups
SELECT dg.arrangerid as id
FROM departmentGroup dg
INNER JOIN department_departmentGroup ddg
ON (dg.id = ddg.departmentGroupId AND ddg.departmentid = @departmentid)
UNION ALL
-- Get Preferred Arrangers linked to Cost Centre Groups
SELECT cg.arrangerid as id
FROM costCentreGroup cg
INNER JOIN costcentre_costCentreGroup ccg
ON (cg.id = ccg.costCentreGroupId AND ccg.costcentreid = @costcentreid)
UNION ALL
-- If Cost Centre Group has a linked department and this department matches
-- the travel arrangers department then return these travel arrangers as well
SELECT t3.id
FROM costCentreGroup cg1
INNER JOIN costcentre_costCentreGroup ccg1
ON (cg1.id = ccg1.costCentreGroupId AND ccg1.costcentreid = @costcentreid)
INNER JOIN traveller t3
ON t3.departmentid = cg1.departmentid
WHERE t3.accesslevelid > 1
UNION ALL
-- Get Direct linked travel arrangers
SELECT t1.travelarrangerid as id
FROM travelarranger_traveller t1
WHERE t1.travellerid = @travellerid
UNION ALL
-- Get Cost Centre linked arrangers
SELECT tc.travelarrangerid as id
FROM travelArranger_costcentre tc
WHERE tc.costcentreid = @costcentreid
UNION ALL
-- Get Department linked arrangers
SELECT td.travelarrangerid
FROM travelArranger_department td
WHERE td.departmentid = @departmentid
UNION ALL
-- Get Company flagged arrangers
SELECT t2.id
FROM traveller t2
INNER JOIN company c ON t2.companyid = c.id
WHERE t2.accesslevelid > 1
AND ((c.allowTravelArrangerDepartmentAccess = 1 AND t2.departmentid = @departmentid)
OR (c.allowTravelArrangerCostCentreAccess = 1 AND t2.costcentreid = @costcentreid))
) as dv ON dv.id = t.id
WHERE t.accessLevelid > 1 -- arranger or manager
AND t.isenabled = 1
ORDER BY dv.preferred DESC, t.lastname, t.firstname;
感謝您的快速和詳細的回覆。對不起,我已經從每個UNION中刪除了「首選」標誌,因爲它沒有必要,我在外部選擇中留下了對它的引用。就像你已經擁有的那樣忽略它。隨着查詢的重寫,它仍然有效地使我處於和以前一樣的位置,從而我無法重用這些規則。這些6/7選擇查詢我以前曾經聯合形成了核心業務規則和相同的確切語句,在系統中的其他5個過程中使用,如果添加新規則,這些過程就會變得更加難以維護。 – 2010-10-07 02:52:35
另外我對每個EXISTS子句的SELECT NULL有點困惑?我原以爲這是在每個子查詢中檢查存在的ID。所以你認爲創建一個可重用的函數是爲了加入更慢的性能,因爲給定的編程人員可能會返回多達4000名遊客?謝謝! – 2010-10-07 02:57:13
@Phil Rasmussen:正如我所解釋的,您希望重用我將重申的邏輯:這是一個糟糕的基礎,旨在實現良好的SQL。從維護的角度來看,對您而言很容易,在現實中可能會導致性能下降。如果權衡是值得的,這取決於你。 – 2010-10-07 02:59:28