2013-09-24 82 views
1

我試圖在T-SQL查詢中修改以下子句以匹配此條件:多個字段的T-SQL條件

如果付款表中存在有效的記錄,則返回true,否則返回false

- 或 -

如果IsPromoted列是真實的,返回true。

CASE 
    WHEN (SELECT COUNT(*) AS Expr1 
      FROM dbo.Payments 
      WHERE (EventId = dbo.Events.EventCode) 
       AND (DATEADD(day, DurationDays, PaymentReceived) 
                > GETDATE())) > 0 THEN 'true' 
    WHEN ispromoted = 1 THEN 'true' 
    ELSE 'false' 
    END AS UpgradedState 

有人可以提出一個更好的方法來實現這個嗎?

+1

你應該做一個左連接而不是這個Count> 0,但是我不能確定,直到你包含你的整個查詢。 – EkoostikMartin

回答

4

我會用EXISTS(SELECT ...)代替(SELECT COUNT(*) FROM ...) > 0

CASE 
    WHEN IsPromoted = 1 THEN 'true' -- See Martin Smith's comment 
    WHEN EXISTS(SELECT * FROM .... dbo.Payments ...) THEN 'true' 
    ELSE 'false' 
END 

如果性能是非常重要的話,我會測試解決方案:

1)我想創建一個計算列:

ALTER TABLE dbo.Payments 
ADD ColumnA AS DATEADD(day, DurationDays, PaymentReceived); 
GO 

2)和我會create an index on this computed column

SET NUMERIC_ROUNDABORT OFF; 
SET ANSI_NULLS ON; 
SET ANSI_PADDING ON; 
SET ANSI_WARNINGS ON; 
SET ARITHABORT ON; 
SET CONCAT_NULL_YIELDS_NULL ON; 
SET QUOTED_IDENTIFIER ON; 
CREATE /*UNIQUE*/ INDEX IX_Payments_EventId_ColumnA 
ON dbo.Payments(EventId, ColumnA); 
GO 

3)我想重寫因此存在:

CASE 
    WHEN IsPromoted = 1 THEN 'true' -- See Martin Smith's comment 
    WHEN EXITS(SELECT * FROM dbo.Payments 
      WHERE EventId = dbo.Events.EventCode 
      AND ColumnA > GETDATE()) THEN 'true' 
    ELSE 'false' 
    END 

另外,我想嘗試以下指標:

CREATE /*UNIQUE*/ INDEX IX_Payments_EventId_#_DurationDays_PaymentReceived 
ON dbo.Payments(EventId) 
INCLUDE(DurationDays, PaymentReceived); 
GO 
+3

+1應該首先檢查'isPromoted',因爲檢查起來更便宜。然後子查詢將在[通過謂詞](http://blogs.msdn.com/b/craigfr/archive/2006/08/23/715306.aspx) –

+0

@MartinSmith:好建議馬丁。謝謝。 –

+1

雖然測試這個想法,但它只有在'EXISTS'的半連接被實現爲嵌套循環時纔會有所作爲。 –

0

請注意,嵌套查詢不是很快。如果你想提高性能,那麼在EventId = p.EventCode上使用dbo.Payments p的LEFT JOIN會更快。以下CASE聲明應該這樣做。

CASE 
WHEN (DATEADD(day, p.DurationDays, p.PaymentReceived) > GETDATE()) > 0 THEN 'true' 
WHEN ispromoted = 1 THEN 'true' 
ELSE 'false'