繁体   English   中英

如何在执行插入的SQL WHILE循环中避免重复的CASE语句

[英]How to avoid repetitive CASE statements in SQL WHILE loop doing INSERT

有没有一种方法可以简化此脚本,以使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

您可以将其包装在一个函数中:

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)
    )

使用函数会产生开销。 您必须确定稍微降低的性能是否值得为提高可读性进行权衡。

是的,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

您可以创建一个临时表,在其中插入计算出的字段,然后将该表与联接一起使用以插入数据/应用条件

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM