簡體   English   中英

從C#到存儲過程重構條件SQL內部聯接

[英]Refactor conditional SQL inner join from C# to Stored Procedure

我有一個存儲庫類,該存儲庫類使用通過在特定條件下串聯字符串的C#構造的查詢。 我想將此查詢從C#代碼移動到存儲過程。 現在,一段代碼根據條件對一個巨大的用戶表(我正在談論數百萬條記錄)進行內部聯接。 這是代碼段。

    StringBuilder sb = new StringBuilder();
    sb.AppendLine("  SELECT");
    sb.AppendLine("  I.[Code] AS ItemCode, IP.[PlatformCode]");
    sb.AppendLine("  FROM [product].[ProductPlatform] PP");
    sb.AppendLine("  JOIN [product].[Product] P ON PP.[ProductId] = P.[Id]");
    if (condition)
    {
        sb.AppendLine("    JOIN [user].[UserItem] UI ON I.[ItemCode] = UI.[ItemCode] AND IP.[PlatformCode] = UI.[PlatformCode] AND UI.[UserId] = @UserId");
    }
    if (condition2)
    {
        sb.AppendLine("    JOIN [user].[UserProductItem] UPI ON I.[Code] = UPI.[ProductItemCode] AND UPI.[UserId] = @UserId");
    }
    ...

還有其他聯接,但並不重要。 現在,如果兩個條件為假,則兩個連接字符串將被完全忽略。 現在,我想將整個SQL代碼移到Stored Proc中,而不會影響性能。 如果條件為假,我不希望執行兩個聯接,因為這兩個表很大。 我創建了以下存儲過程,在該過程中,我將兩個C#條件變量作為參數傳遞給我的存儲過程,但是我認為a)邏輯不完全相同,就好像條件不滿足,查詢什么也不返回,我想我需要左加入和b)不能像以前那樣保留性能。

    JOIN [user].[UserItem] UI ON a.[ItemCode] = UI.[ItemCode] AND PP.[PlatformCode] = UI.[PlatformCode] AND UI.[UserId] = @UserId AND (@onlyConditionMet = 1)


    JOIN [user].[UserProduct] UP ON P.[Code] = UP.[ProductCode] AND UP.[UserId] = @UserId AND (@onlyCondition2Met = 1)

現在的問題是,如何通過保持性能而不過多改變查詢的方式將代碼最好地移動到存儲的proc中。

更新 :基於這里人們提出的解決方案,我最終使用了IF塊。 我的代碼現在很冗長,但是我保留了性能,這對於我的查詢而言至關重要。 現在我的代碼如下:

    IF ( condition1 = true AND condition2 = true AND condition3 = true)
        BEGIN
            SELECT * FROM someTable
            LEFT JOIN someOtherTable on someCondition
        END
    ELSE IF ( condition1 = true AND condition2 = true AND condition3 = false)
        BEGIN
            SELECT * FROM someTable
            LEFT JOIN someOtherThanTheOtherTable on someOtherCondition
        END
    ...
    ELSE IF ( condition1 = false AND condition2 = false AND condition3 = false)
        BEGIN
            -- Do something else
        END

只需使:

IF @condition = 1
[...  First SELECT WITH first JOIN ... ]
ELSE
[...  Second SELECT WITH second JOIN ... ]

此外,就性能而言,將Ado與“動態查詢”配合使用可使SQL Server每次重新編譯查詢並處理新的執行計划。 使用存儲過程或函數將比Ado中的動態查詢更快,因為在將查詢添加到數據庫時,該查詢僅被編譯一次。

此外之二:如果您的過程中只有一些SELECT語句,並且每次返回的值相同,為什么不使用Table Function?

PS:從性能的角度來看,不能確定JOIN子句中的布爾值是否比IF / THEN情況下的效率低。 您應該查看執行計划並進行一些測試。 SQL Server有時確實很聰明。

總有sq_executesql ,但您可能需要將其寫為高級IF塊:

If condition And NOT condition2
Begin

 -- Do query with UserItem join

end
if (NOT condition) And condition2
Begin

 -- Do query with UserProduct join

end
if condition And condition2

 -- Do query with both joins

end

最后,根據您的條件,您可以使用OUTER JOIN類型將它們寫入JOIN子句:

LEFT JOIN [user].[UserItem] UI ON condition AND I.[ItemCode] = UI.[ItemCode] AND IP.[PlatformCode] = UI.[PlatformCode] AND UI.[UserId] = @UserId 

您提到了性能問題,因此,我要補充一點,如果為您的條件引用的列是恆定的或與表索引很好地匹配,則最后一個選項仍然可以很好地執行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM