2015-12-11 52 views
2

是否有可能建立在SQL Server中查找類型的功能或者是這些劣質總是(性能),只是寫的子查詢/加入?SQL服務器查找函數

我想採取一些這樣的代碼

SELECT 
    ContactId, 
    ProductType, 
    SUM(OrderAmount) TotalOrders 
FROM 
    (
     SELECT 
      ContactId, 
      ProductType, 
      OrderAmount 
     FROM 
      UserOrders ord 
      JOIN 
      (
       SELECT 
        ProductCode, 
        CASE 
         --Complex business logic 
        END ProductType 
       FROM 
        ItemTable 
      ) item 
      ON 
       item.ProductCode=ord.ProductCode 

    ) a 
GROUP BY 
    ContactId, 
    ProductType 

,而是能夠寫一個這樣的查詢

SELECT 
    ContactId, 
    UDF_GET_PRODUCT(ProductCode) ProductType, 
    SUM(OrderAmount) TotalOrders 
FROM 
    UserOrders 
GROUP BY 
    ContactId, 
    UDF_GET_PRODUCT(ProductCode) 

回答

1

這是可能的,但不是所描述的格式。這是否合理取決於。

我與該標量函數對方的回答都是一致的性能殺手,我個人完全不使用它們。 這就是說,我不認爲這是在可行的情況下忽略DRY原則的理由。即如果它對性能有影響,我不會採取快捷方式 ,但是我也不喜歡在多個地方重複複雜邏輯的想法。 如果一切都改變了你那麼有多個查詢改變,難免有些被錯過了,所以如果你將這個 邏輯重新使用那麼它是一個好主意,它封裝在一個地方。基於

你的例子也許是一個視圖是最合適的:

CREATE VIEW dbo.ItemTableWithLogic 
AS 
    SELECT ProductCode, 
      ProductType = <your logic> 
    FROM ItemTable; 

然後,你可以簡單地使用:

SELECT ord.ContactId, item.ProductType, SUM(ord.OrderAmount) AS TotalOrders 
FROM UserOrders AS ord 
     INNER JOIN dbo.ItemTableWithLogic AS item 
      ON item.ProductCode=ord.ProductCode 
GROUP BY ord.ContactId, item.ProductType; 

這在一定程度簡化了操作。

另一種選擇是值函數內聯表,是這樣的:

CREATE FUNCTION dbo.GetProductType (@ProductCode INT) 
RETURNS TABLE 
AS 
RETURN 
( SELECT ProductType = <your logic> 
    FROM ItemTable 
    WHERE ProductCode = @ProductCode 
); 

可使用被稱爲:

SELECT ord.ContactId, item.ProductType, SUM(ord.OrderAmount) AS TotalOrders 
FROM UserOrders AS ord 
     CROSS APPLY dbo.ItemTableWithLogic(ord.ProductCode) AS item 
GROUP BY ord.ContactId, item.ProductType; 

我的選擇是對享有表值函數,然而,這將真的取決於你的用法,我會推薦的,所以我不想挑一邊,我會堅持坐在圍欄上。

總之,如果你只需要使用的邏輯在一個地方,而不必再使用它在許多查詢然後只是堅持一個子查詢。如果您需要多次重複使用相同的邏輯,請不要像過程語言中那樣使用標量值函數,也不要讓這種排除其他方法來將您的邏輯保存在一個地方。

1

棒子查詢和連接。

,因爲它會使用一組爲基礎的方法和執行一次內部查詢,以將其從內部查詢返回的結果集將集合並返回最終的結果集。

另一方面,如果您使用第二個查詢中顯示的標量函數,函數中的所有代碼(原始問題中的子查詢)將針對返回的每一行執行。

標量函數是性能殺手,應避免他們只要有可能。這是.net的心態,如果你不得不一次性地寫一段代碼並將其放入一個方法並調用該方法,那麼對於sql server來說不是這樣。