Date ranges in T/SQL

前端 未结 4 951
北荒
北荒 2021-01-15 06:44

For a current project I am working I need to return an aggregate report based on date ranges.

I have 3 types of reports, yearly, monthly and daily.

To assis

相关标签:
4条回答
  • 2021-01-15 07:04

    From a performance standpoint, you will not want to use a function to generate the date ranges. For each evaluation in the query ( @myDate > dbo.MyFunc() ), the function will have to execute fully. Your best bet is to build static numbers table.

    Now on with the numbers tables....

    This is a fast way to create a integers table. (Props to Jeff Moden for the Identity Trick)

     SELECT TOP 1000000
            IDENTITY(INT,1,1) as N
       INTO dbo.NumbersTable
       FROM Master.dbo.SysColumns 
            Master.dbo.SysColumns 
    

    Less than 2 seconds to populate 1000000 numbers in a table.

    Now to address your problem, you will need to use this to build a table of dates. The example below will create a table with the zero hour (12AM) for each day starting from the @startDate

    DECLARE @DaysFromStart int
    DECLARE @StartDate datetime
    SET @StartDate = '10/01/2008'
    
    SET @ DaysFromStart  = (SELECT (DATEDIFF(dd,@StartDate,GETDATE()) + 1))
    
    CREATE TABLE [dbo].[TableOfDates](
        [fld_date] [datetime] NOT NULL,
     CONSTRAINT [PK_TableOfDates] PRIMARY KEY CLUSTERED 
    (
        [fld_date] ASC
    )WITH FILLFACTOR = 99 ON [PRIMARY]
    ) ON [PRIMARY]
    
    
    INSERT INTO
         dbo.TableOfDates
    SELECT 
          DATEADD(dd,nums.n - @DaysFromStart ,CAST(FLOOR(CAST(GETDATE() as FLOAT)) as DateTime)) as FLD_Date
    FROM #NumbersTable nums
    
    SELECT MIN(FLD_Date) FROM dbo.TableOfDates
    SELECT MAX(FLD_Date) FROM dbo.TableOfDates
    

    Now with different combinations of DATEADD/DIFF, you should be able to create the static tables that you will need to do many date range queries efficiently.

    0 讨论(0)
  • 2021-01-15 07:06

    A static number table is useful, single column, say 8000 rows FROM 0 TO 7999

    (Not checked)

    DECLARE @Start smalldatetime, @End smalldatetime, @Diff int
    
    SELECT @Start = '2006-01-01 11:10:00', @End = '2009-05-05 08:00:00', @diff = DATEDIFF(year,@start,@end)
    
    SELECT
       DATEADD(year,N.Number,@Start)
    FROM
       dbo.Number N
    WHERE
       N.Number <= @diff
    
    0 讨论(0)
  • 2021-01-15 07:12

    There are quite a few tricks in here, hope you find it useful

    create function dbo.fnGetDateRanges
    (
        @type char(1),
        @start datetime,
        @finish datetime
    )
    returns @ranges table(start datetime, finish datetime)
    as 
    begin
    
        declare @from datetime 
        declare @to datetime 
        set @from = @start 
    
        if @type = 'd'
        begin 
            set @to = dateadd(day, 1,
                    convert
                    (   datetime,
                        cast(DatePart(d,@start) as varchar) + '/' + cast(DatePart(m,@start) as varchar) + '/' + cast(DatePart(yy,@start) as varchar),
                        103
                    )
                )
        end
    
        if @type = 'm'
        begin
            set @to = dateadd(month, 1, 
                convert
                (   
                    datetime,
                    '1/' + cast(DatePart(m,@start) as varchar) + '/' + cast(DatePart(yy,@start) as varchar),
                    103
                )
            )
        end 
    
        if @type = 'y'
        begin
            set @to = dateadd(year, 1, 
                convert
                (   
                    datetime,
                    '1/1/' + cast(DatePart(yy,@start) as varchar),
                    103
                )
            )
        end 
    
        while @to < @finish
        begin 
            insert @ranges values (@from, @to)
            set @from = @to 
            if @type = 'd'
                set @to = dateadd(day, 1, @to)
            if @type = 'm'
                set @to = dateadd(month, 1, @to)
            if @type = 'y'
                set @to = dateadd(year, 1, @to)
        end
    
        insert @ranges values (@from, @finish)
    
        return 
    end
    
    0 讨论(0)
  • 2021-01-15 07:19

    If you prefer a set-based solution, use a tactic like the one shown in the following link to produce a range of numeric values from x to y. Then, just join to it with DATEADD() and your own custom limits to create ranges of days, months, quarters, years, or whatever else. I find it helpful to have this range query as a view.

    Generate Ranges In SQL

    0 讨论(0)
提交回复
热议问题