2

I'm trying to use this ExplodeDate function.

But I dont't get it run with one easy query. I can reproduce this with an empty database on SQL Server 2016 locally and in an Azure Database.

Please use following code to reproduce the issue.

Code for used functions:

/*
    FUNCTION:   [dbo].[ExplodeDates]
*/
DROP FUNCTION IF EXISTS [dbo].[ExplodeDates]
GO
CREATE FUNCTION [dbo].[ExplodeDates](@startdate datetime, @enddate datetime)
returns table as
return (
with 
 N0 as (SELECT 1 as n UNION ALL SELECT 1)
,N1 as (SELECT 1 as n FROM N0 t1, N0 t2)
,N2 as (SELECT 1 as n FROM N1 t1, N1 t2)
,N3 as (SELECT 1 as n FROM N2 t1, N2 t2)
,N4 as (SELECT 1 as n FROM N3 t1, N3 t2)
,N5 as (SELECT 1 as n FROM N4 t1, N4 t2)
,N6 as (SELECT 1 as n FROM N5 t1, N5 t2)
,nums as (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) as num FROM N6)
SELECT DATEADD(day,num-1,@startdate) as [Date]
FROM nums
WHERE num <= DATEDIFF(day,@startdate,@enddate) + 1
);
GO


/*
    FUNCTION:   [dbo].[ExplodeDatesByPeriod]
*/
DROP FUNCTION IF EXISTS [dbo].[ExplodeDatesByPeriod]
GO
CREATE FUNCTION [dbo].[ExplodeDatesByPeriod]
(
    @StartDate DATE = '20130101', 
    @EndDate DATE ='20301231',
    @ImpactPeriod INT = 4       -- 4 Jahr, 3 Quartal, 2 Monat, 1 Woche, 0 Tag  - siehe ImpactPeriod
)
RETURNS TABLE
AS
RETURN(
    WITH CTE 
    AS
    (
        SELECT 
                  [Date]
                , CASE 
                        WHEN @ImpactPeriod = 0 THEN DATEPART(YEAR, [Date])
                        -- MORE WHEN CASES HERE ....
                        ELSE Year([Date])
                    END AS [Year]
                , CASE 
                        WHEN @ImpactPeriod = 0 THEN DATEPART(DAYOFYEAR, [Date])
                        -- MORE WHEN CASES HERE ....
                        ELSE Year([Date])
                    END AS [Period]
            FROM [dbo].[ExplodeDates](CASE 
                                            WHEN @ImpactPeriod = 0 THEN @StartDate
                                            -- MORE WHEN CASES HERE ....
                                            ELSE DATEFROMPARTS(YEAR(@StartDate), 1, 1)
                                        END, @EndDate)  
    )
    SELECT 
                MIN([Date])  AS [StartOfPeriod]
            , CASE 
                    WHEN @ImpactPeriod = 0 THEN MIN([Date])
                    -- MORE WHEN CASES HERE ....
                    ELSE DATEFROMPARTS(DATEPART(YEAR, MIN([Date])), 12, 31)
                END AS [EndOfPeriod]
            , ([Year] * ( CASE 
                            WHEN @ImpactPeriod = 0 THEN 1000
                            -- MORE WHEN CASES HERE ....
                            ELSE 0
                        END)
                ) + [Period] AS [YearPeriod]
            , [Year]
            , [Period]
        FROM [CTE]
        GROUP BY                
                [Year]
            , [Period]

)
GO

Then if you run following code it never ends:

/*
    TABLE WITH DUMMY DATA
*/
DROP TABLE IF EXISTS [T1]
CREATE TABLE [T1](
    [StartDate] DATE,
    [EndDate] DATE
)
INSERT INTO [T1] VALUES ('20190101', '20190101')
GO

/*
    FUNCTION CALL TO:   [dbo].[ExplodeDates]  DOESN'T WORK!!
*/
SELECT * FROM [T1] CROSS APPLY [dbo].[ExplodeDates]([T1].[StartDate], [T1].[EndDate]) [D]
GO

The interesting thing is, that following query executes immediately:

/*
    FUNCTION CALL TO:   [dbo].[ExplodeDatesByPeriod]  THIS WORKS!!
                        PARAM 0 for Days
*/
SELECT * FROM [T1] CROSS APPLY [dbo].[ExplodeDatesByPeriod]([T1].[StartDate], [T1].[EndDate], 0) [D]
GO

[dbo].[ExplodeDatesByPeriod] is calling [dbo].[ExplodeDates] internally!

Daniel C.
  • 569
  • 2
  • 7
  • 19
  • 1
    As an aside, a dedicated `nums` table for this stuff tends to be better than the recursive CTE dance. It's more transparent to the optimizer. – Jeroen Mostert Apr 13 '18 at 11:55
  • 1
    Well a dedicated calendar table rather than nums one. – wBob Apr 13 '18 at 14:21
  • Sure Num or Date table might be the better solution, but this doesn't explain why my query never returns even with only one row in my table. – Daniel C. Apr 16 '18 at 06:26
  • Works as expected in [this SQL fiddle](http://sqlfiddle.com/#!18/c4444/8). Which part of the function keeps running if you debug it? – Sander May 02 '18 at 10:52
  • I tested your fiddle and it works for me too. I also tested SQL 2016 and Azure Database, and it works now too. Unfortunately i cannot reproduce my issue at this time... – Daniel C. May 03 '18 at 20:09

0 Answers0