请注意我的脚本 - 如何提高效率

时间:2018-02-16 10:03:17

标签: sql-server tsql

我有一个表(SYS_Holidays),它有每个假期的开始和结束日期。我需要以关系形式输出所有假日日期。例如,我在2017年12月25日到2018年1月2日作为输入中的一行,我想输出25-Dec,26-Dec ...到2月1日为9行。

我写过这个剧本,请你告诉我如何才能提高效率?

SELECT 
    H.HolidayName
    , DATEADD(DAY, Number-1, H.StartDate) AS HolidayDate
FROM 
    SYS_Holidays AS H
    CROSS JOIN Config_Numbers AS N 
WHERE 
    -- Figure the # of days between start and end: one row for each holiday-date
    -- If EndDate is null, just use StartDate (i.e. 1-day holiday)
    N.Number <= DATEDIFF(DAY, H.StartDate, ISNULL(H.EndDate, H.StartDate) ) + 1 

注意:Config_Numbers是我用巨大整数列表创建的表(如BIGINT)

2 个答案:

答案 0 :(得分:1)

可以使用日期表和内部联接来完成。如果子表不够高效,请使用子查询来创建表:

Create table #Test (HolidayName nvarchar(100), StartDate Date, EndDate Date)

Insert Into #Test Values ('Christmas', '2017-12-22', '2018-01-03'), ('Easter' , '2017-04-10', '2017-04-16')

SELECT HolidayName, DatesList.[Date] as HolidayDate
FROM #Test t
inner join (
    SELECT cast(dateadd(day, number, '2017-1-1') as date) as [Date]
     FROM master..spt_values WHERE type='P' AND number < 1000) AS DatesList 
        on t.StartDate<=DatesList.[Date] and t.EndDate>=DatesList.[Date]

答案 1 :(得分:0)

我修改了@ cloudsafe的答案,以产生下面的代码。它仍然 比使用Config_Numbers的任何联接更快。子树的成本达到了0.2785。

我认为2048可以覆盖5年多一点,所以我把我的代码分成了5年的块,然后让UNION加入他们。

麻烦的是,我必须记住每隔5年再做一次UNION: - (

SELECT HolidayName, DatesList.[Date] as HolidayDate
FROM SYS_Holidays AS H
inner join (
    SELECT cast(dateadd(day, number, '2013-01-01') as date) as [Date]
     FROM master..spt_values WHERE type='P' AND number < 2048) AS DatesList 
        on H.StartDate <= DatesList.[Date] and H.EndDate >=DatesList.[Date]

UNION

SELECT HolidayName, DatesList.[Date] as HolidayDate, H.HolidayId, H.CampusId, H.CategoryId
FROM SYS_Holidays AS H
inner join (
    SELECT cast(dateadd(day, number, '2018-01-01') as date) as [Date]
     FROM master..spt_values WHERE type='P' AND number < 2048) AS DatesList 
        on H.StartDate <= DatesList.[Date] and H.EndDate >=DatesList.[Date]

还有其他改进建议吗?