1

この条件に一致するように、T-SQL クエリの次の句を変更しようとしています。

支払いテーブルに有効なレコードが存在する場合は true を返し、そうでない場合は false を返します。

- また -

列が trueの場合、IsPromotedtrue を返します。

   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 

これを達成するためのより良い方法を誰かが提案できますか?

4

2 に答える 2

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) そして、この計算列にインデックスを作成します

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) EXISTS を次のように書き直します。

  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
于 2013-09-24T20:10:36.483 に答える
0

ネストされたクエリはあまり高速ではないことに注意してください。パフォーマンスを向上させたい場合は、dbo.Payments p on EventId = p.EventCode を使用した LEFT JOIN の方が高速に動作します。次の CASE ステートメントでそれを行う必要があります。

 CASE
 WHEN (DATEADD(day, p.DurationDays, p.PaymentReceived) > GETDATE() ) > 0 THEN 'true'
 WHEN ispromoted = 1 THEN 'true'
 ELSE 'false'
于 2013-09-24T20:36:32.050 に答える