0

CASE ステートメントが重複しないように、このスクリプトを単純化する方法はありますか? この短縮された例では許容できるように見えますが、実際には、「2 週間ごと」、「4 週間ごと」、「毎月」などのケースがあるため、CASE ステートメントははるかに長くなります。パフォーマンスのために SQL Server と WHILE ステートメントを使用しています。理由. CTE または MERGE は役に立ちますか?

        DECLARE @theStartDate DATE
DECLARE @Interval INT
DECLARE @eventCharges TABLE
(
    [EventDate] [datetime],
    Person_Id int
)

SET @today = GETDATE()
SET @Interval = 0

-- delete event charges from previous user  
DELETE FROM @eventCharges

-- Insert the calculated transactions   
WHILE @Interval < 100
BEGIN
SET @Interval = @Interval + 1
INSERT INTO @eventCharges
SELECT
    CASE
        WHEN pcc.Recurrence = 'Daily' 
        THEN DATEADD(DAY, @Interval, @theStartDate)
        WHEN pcc.Recurrence = 'Weekly'
        THEN DATEADD(WEEK, @Interval, @theStartDate)            
    END AS EventDate
    ,pcc.Person_Id
FROM @personChargeCurrent pcc   
WHERE CASE
            WHEN pcc.Recurrence = 'Daily' 
            THEN DATEADD(DAY, @Interval, @theStartDate)
            WHEN pcc.Recurrence = 'Weekly'
            THEN DATEADD(WEEK, @Interval, @theStartDate)
        END <= @today
    AND NOT EXISTS(SELECT 1 FROM dbo.PersonChargeTransaction pct 
                    WHERE pct.Person_Id = pcc.Person_Id
                    AND pct.PersonCharge_Id = pcc.Id
                    AND pct.TransactionDate = 
                    CASE
                        WHEN pcc.Recurrence = 'Daily' 
                        THEN DATEADD(DAY, @Interval, @theStartDate)
                        WHEN pcc.Recurrence = 'Weekly'
                        THEN DATEADD(WEEK, @Interval, @theStartDate)
                    END)
ORDER BY StartDate
END
4

3 に答える 3

2

これを関数でラップできます。

Create Function dbo.IntervalEnd(
    @recurrence varchar(10),
    @interval int,
    @startDate date -- or whatever data type you're using for dates
) returns date as
begin
    return case
        when @recurrence = 'Daily' then dateadd(day, @interval, @startDate)
        when @recurrence = 'Weekly' then dateadd(week, @interval, @startDate)
    end
end

それで

Insert Into @eventCharges
Select
    dbo.IntervalEnd(pcc.Recurrence, @Interval, @theStartDate) as EventDate,
    pcc.Person_Id
From
    @personChargeCurrent pcc   
Where
    dbo.IntervalEnd(pcc.Recurrence, @Interval, @theStartDate) <= @today And
    Not Exists (
        Select
            1
        From
            dbo.PersonChargeTransaction pct 
        Where
            pct.Person_Id = pcc.Person_Id And
            pct.PersonCharge_Id = pcc.Id And
            pct.TransactionDate 
                = dbo.IntervalEnd(pcc.Recurrence, @Interval, @theStartDate)
    )

関数を使用するためのオーバーヘッドがあります。わずかに低下したパフォーマンスが、読みやすさのトレードオフに値するかどうかを判断する必要があります。

于 2013-10-27T12:11:18.127 に答える
1

はい、CTE が役に立ちます。INSERT ステートメントを次のように変更してみてください。

WITH cte as 
(SELECT CASE
            WHEN Recurrence = 'Daily' 
            THEN DATEADD(DAY, @Interval, @theStartDate)
            WHEN Recurrence = 'Weekly'
            THEN DATEADD(WEEK, @Interval, @theStartDate)            
        END AS EventDate,
        p.*
 FROM @personChargeCurrent p)
INSERT INTO @eventCharges
SELECT cte.EventDate, cte.Person_Id
FROM cte
WHERE cte.EventDate <= @today AND 
      NOT EXISTS
      (SELECT 1 
       FROM dbo.PersonChargeTransaction pct 
       WHERE pct.Person_Id = cte.Person_Id AND 
             pct.PersonCharge_Id = cte.Id AND 
             pct.TransactionDate = cte.EventDate)
ORDER BY StartDate
于 2013-10-27T12:23:05.507 に答える
0

計算フィールドを挿入する一時テーブルを作成し、そのテーブルを結合で使用してデータを挿入/条件を適用することができます

于 2013-10-27T12:04:07.510 に答える