使用子查询重写/优化T-SQL存储过程

时间:2014-11-09 19:13:43

标签: sql sql-server tsql subquery

我有一个存储过程,现在我不是一个DBA,所以我只是想知道这是否被认为是不好的做法,因为我有很多子查询具有基本相同的代码。

我应该使用表变量还是临时表?

此外,我必须重新编写第二个查询作为动态SQL,因为我只想包含基于标志的联合,因此临时表在这里会更容易。

感谢您的帮助

CREATE TABLE #Days(theDate datetime, DayAsString varchar(15))

CREATE TABLE #temp(id int identity(1,1),trip_date datetime, trip_return datetime, iteration int, weeknumber int)

IF @SpecificDay = 0
Begin 
    INSERT INTO #Days 
            SELECT [date] ,DATENAME(dw,[date])
                FROM dbo.Calendar C 
                WHERE [Date] BETWEEN @start AND @end
                     AND C.[WkDName] in (select distinct siDay.Name
                                                from schedule s
                                                join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
                                                join scheduleInterval sint       on sim.scheduleIntervalID = sint.id
                                                left join ScheduleItem siDay     on sim.scheduleDayItemId = siDay.id            
                                                where s.schedule_id = @schedule_id
                                                ) --@wkDName
                     AND C.[Month] in (select distinct siMonth.Id
                                                from schedule s
                                                join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
                                                join scheduleInterval sint       on sim.scheduleIntervalID = sint.id                                
                                                join ScheduleItem siMonth        on sim.ScheduleMonthItemId = siMonth.id
                                                where s.schedule_id =  @schedule_id
                                                ) --@Month
                     AND C.[WkNo] in (select distinct sint.Id
                                                from schedule s
                                                join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
                                                join scheduleInterval sint       on sim.scheduleIntervalID = sint.id                                
                                                join ScheduleItem siDay        on sim.ScheduleDayItemId = siDay.Id
                                                where s.schedule_id =  @schedule_id)          --@first last etc @occurence
                Union all --include the last occurence of the month
                SELECT [date] ,DATENAME(dw,[date])
                FROM dbo.Calendar CLast
                WHERE [Date] BETWEEN @start AND @end
                     AND CLast.[WkDName] in (select distinct siDay.Name
                                                from schedule s
                                                join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
                                                join scheduleInterval sint       on sim.scheduleIntervalID = sint.id
                                                left join ScheduleItem siDay     on sim.scheduleDayItemId = siDay.id            
                                                where s.schedule_id =  @schedule_id
                                                ) --@wkDName
                     AND CLast.[Month] in (select distinct siMonth.Id
                                                from schedule s
                                                join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
                                                join scheduleInterval sint       on sim.scheduleIntervalID = sint.id                                
                                                join ScheduleItem siMonth        on sim.ScheduleMonthItemId = siMonth.id
                                                where s.schedule_id =  @schedule_id
                                                ) --@Month
                     AND CLast.[Last] = 1
    END 
ELSE --Specific date has been specified or last has been selected
    INSERT INTO #Days 
    select distinct [date] ,DATENAME(dw,[date]) from 
    (
        SELECT *
        FROM dbo.Calendar C 
        WHERE [Date] BETWEEN @start AND @end
             AND C.[Month] in (select distinct siMonth.Id
                                        from schedule s
                                        join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
                                        join scheduleInterval sint       on sim.scheduleIntervalID = sint.id                                
                                        join ScheduleItem siMonth        on sim.ScheduleMonthItemId = siMonth.id
                                        where s.schedule_id = @schedule_id) --@Month
             AND C.[Day] in (select distinct sint.Name
                                        from schedule s
                                        join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
                                        join scheduleInterval sint       on sim.scheduleIntervalID = sint.id                                
                                        join ScheduleItem siMonth        on sim.ScheduleMonthItemId = siMonth.id
                                        where s.schedule_id = @schedule_id
                                        AND sint.Name <> 'Last'
             )
        Union all --include the last occurence of the month IF LAST
        SELECT *
        FROM dbo.Calendar CLast
        WHERE [Date] BETWEEN @start AND @end
             AND CLast.[Month] in (select distinct siMonth.Id
                                        from schedule s
                                        join ScheduleItemIntervalMap sim on s.schedule_id = sim.scheduleid
                                        join scheduleInterval sint       on sim.scheduleIntervalID = sint.id                                
                                        join ScheduleItem siMonth        on sim.ScheduleMonthItemId = siMonth.id
                                        where s.schedule_id = @schedule_id
                                        ) --@Month
                                        AND [Date] in (select LDtOfMo from dbo.Calendar 
                                                        WHERE [Date] BETWEEN @start AND @end)
            ) as x


Begin 
        INSERT INTO #temp(trip_date,trip_return,iteration,weeknumber)
        SELECT 
            theDate + CAST(@timeout AS DATETIME),theDate+ CAST(@timeback AS DATETIME),@WeekNo,DATEPART(wk, theDate+CAST(@timeout AS DATETIME))
        FROM
            #Days           
        END

1 个答案:

答案 0 :(得分:0)

因为你反复做同样的JOIN;您可以转换JOIN中的子查询,如下所示

INSERT INTO #Days 
        SELECT DISTINCT C.[date] ,DATENAME(dw,C.[date])
            FROM dbo.Calendar C 
            left join ScheduleItem si
            ON si.Name = C.[WkDName]
            AND si.Id = C.[Month]
            JOIN ScheduleItemIntervalMap sim ON sim.scheduleDayItemId = si.id
            JOIN schedule s ON s.schedule_id = sim.scheduleid
            JOIN scheduleInterval sint on sim.scheduleIntervalID = sint.id
            AND sint.Id = C.[WkNo]
            where s.schedule_id = @schedule_id
            AND C.[Date] BETWEEN @start AND @end