0

有没有办法简化这个脚本,使 CASE 语句不重复?在这个缩短的示例中看起来可以接受,但实际上 CASE 语句要长得多,因为我有“每 2 周”、“每 4 周”、“每月”等案例。我使用 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 回答