2011-02-07 30 views
6

Tôi có một thủ tục lưu trữ mà không một cái gì đó như:Có thay thế logic điều kiện bằng các câu lệnh CASE hiệu quả trong Transact-SQL không?

IF @Param = '1' 
    SELECT HT.HeaderKey, HT.Description, 
      (SELECT SUM(E1) -- E1 is actually a complex expression 
      FROM DetailTable DT INNER JOIN ... 
            INNER JOIN ... 
            INNER JOIN ... 
      WHERE DT.HeaderKey = HT.HeaderKey) 
    FROM HeaderTable HT 
ELSE IF @Param = '2' 
    SELECT HT.HeaderKey, HT.Description, 
      (SELECT SUM(E2) -- E2 is yet another complex expression 
      FROM DetailTable DT INNER JOIN ... -- Here, DetailTable is not 
            INNER JOIN ... -- joined to the same tables 
            INNER JOIN ... -- as in the first case 
      WHERE DT.HeaderKey = HT.HeaderKey) 
    FROM HeaderTable HT 
-- Etc. There are five cases. 

tôi muốn để giảm truy vấn như sau:

SELECT HT.HeaderKey, HT.Description, 
     CASE @Param 
     WHEN '1' 
      (SELECT SUM(E1) 
      FROM DetailTable DT INNER JOIN ... 
            INNER JOIN ... 
            INNER JOIN ... 
      WHERE DT.HeaderKey = HT.HeaderKey) 
     WHEN '2' 
      (SELECT SUM(E2) 
      FROM DetailTable DT INNER JOIN ... 
            INNER JOIN ... 
            INNER JOIN ... 
      WHERE DT.HeaderKey = HT.HeaderKey) 
     -- Etc. 
     ELSE 0 
     END 
FROM HeaderTable HT 

Tuy nhiên, nếu SQL Server đánh giá tất cả các trường hợp , bất kể cái nào sẽ thực sự được trả lại, truy vấn đã sửa đổi sẽ không hiệu quả.

Vì vậy, tôi muốn biết, không SQL Server đánh giá tất cả các trường hợp trong một tuyên bố CASE, hoặc chỉ là người đầu tiên thỏa mãn điều kiện của CASE?

+0

1 cho câu hỏi hay –

+0

Cảm ơn, Stephanie. – pyon

Trả lời

2

Tuyên bố CASE của SQL Server, như được đề cập trong this article, tận dụng lợi thế của việc đoản mạch như vậy trong ví dụ cho thấy nó sẽ không đánh giá kết quả của mọi kết quả CASE có thể cho mỗi hàng.
Tuy nhiên, bạn vẫn sẽ nhận được truy vấn kém hiệu quả hơn định dạng hiện tại của bạn vì bạn sẽ buộc tất cả các kết quả để chia sẻ cùng một kế hoạch thực hiện, có thể không tối ưu. Tùy thuộc vào sự khác biệt giữa các truy vấn con CASE, hiệu ứng có thể khá đáng kể.

+0

Định dạng hiện tại của anh ấy buộc mỗi truy vấn chia sẻ cùng một kế hoạch như thế nào? Định dạng hiện tại có các truy vấn riêng biệt. Mỗi người có một số khác biệt ở đâu đó, nếu họ không thì tại sao lại là vụ án? –

+0

Nó sẽ chỉ thêm một đường dẫn khác trong kế hoạch cho mỗi kết quả 'trường hợp '. Không có lý do cụ thể nào để nghĩ rằng con đường bổ sung sẽ khiến các phần khác của kế hoạch trở nên tồi tệ hơn. –

+0

Bạn đang đọc câu trả lời của tôi sai - nó nói "sẽ vẫn nhận được một truy vấn ít hiệu quả THAN định dạng CURRENT của bạn". Phần thứ hai của OP là định dạng được đề xuất của họ, ít hiệu quả hơn định dạng hiện tại của họ (mặc dù có thể dễ bảo trì hơn một chút). – MartW

-1

Bạn sẽ hầu như luôn nhận được kết quả nhanh hơn với giải pháp dựa trên bộ so với giải pháp dựa trên thủ tục trong SQL Server (và tất cả RDMS).

+0

Nó được thiết lập dựa trên. Anh ta hỏi "bộ" nào sẽ nhanh hơn. –

+0

Nếu các câu lệnh không được thiết lập dựa trên SQL Server. – richard

+0

Phải, nhưng sau IF, sẽ có một câu lệnh SQL được thi hành. Các "công việc" đang được thực hiện trong một SET ... đánh giá của một IF là ít hơn so với âm lịch so với sql. Bạn đang dùng một câu châm ngôn đơn giản đến mức cực đoan. Chúng tôi nói rằng thiết lập dựa trên là tốt hơn, không có nghĩa là dòng mã đầu tiên giết chết hiệu suất. Nó có nghĩa là không lặp và xử lý các bảng theo hàng. –

2

Không có thêm "vị từ passthru" vào kế hoạch đảm bảo rằng nó chỉ đánh giá các truy vấn cần thiết. Xem Subqueries in CASE Expressions

0

giả định rằng tham gia đều giống nhau ở mỗi subquery, tôi muốn thử một cái gì đó như thế này:

;with dt as 
(
    select 
     HeaderKey, 
     sum(case @Param 
      when 1 then E1 
      when 2 then E2 
      ...) as ExpressionSum 
    from DetailTable DT 
     inner join... 
    group by dt.HeaderKey 
) 
select 
    ht.HeaderKey, 
    ht.description, 
    dt.ExpressionSum 
from HeaderTable HT 
    inner join dt 
     on HT.HeaderKey=dt.HeaderKey 

hoặc i có thể là sự hiểu lầm hiển nhiên những gì bạn đang cố gắng làm;)

+1

"Ở đây, DetailTable không được tham gia vào cùng một bảng như trong trường hợp đầu tiên." THÔNG BÁO nhận xét. Nó không phải là cùng một bảng ... –

+0

@stephanie, không thấy điều đó, cảm ơn – DForck42

+0

Tôi đã bỏ lỡ nó quá ... –

Các vấn đề liên quan