12

The UI design for storing event and event meta data is

enter image description here

SQL TABLE DESIGN is

CREATE TABLE [dbo].[EVENTS]
([ID] [int] IDENTITY(1,1) NOT NULL,
 [Name] [nvarchar](255) NOT NULL)

and

CREATE TABLE [dbo].[EVENTS_META](
[ID] [int] IDENTITY(1,1) NOT NULL,
[event_id] [int] NOT NULL,
[meta_key] [varchar](255) NOT NULL,
[meta_value] [bigint] NOT NULL)

The Events data is Event

Event Metadata is Events_Meta table

I Followed Repeating calendar events and some final maths and I wrote the below query

LIST ALL THE EVENT DATES BEFORE THE GIVEN END DATE

SELECT EV.*
FROM events AS EV
RIGHT JOIN events_meta AS EM1 ON EM1.event_id = EV.id
RIGHT JOIN events_meta AS EM2 ON EM2.meta_key = 'repeat_interval_'+ CAST(EM1.id as Varchar(100))
WHERE EM1.meta_key = 'repeat_start'
AND ((1391040000 - EM1.meta_value ) % EM2.meta_value) = 0

I am not getting anything. I want to display all dates after repeat_start with the given interval.

Example here 1st event starts on (3rd Jan 2014, 10 A.M) unixtimestamp =1388743200 and continues every friday(7 days), we also schedule the first event on starts saturday(Jan04, 2014)1388858400 and continues once in every 7 days(saturday)

It can be once in a month/daily/etc. So we have the interval defined as seconds.

If i give some input like 30 Jan 2014 , i.e =1391040000 (30 Jan 2014 00:00:00)

Expected Result

Billa Visit, 3 Jan 2014 10 A.M

Billa Visit, 4 Jan 2014 10 A.M

Billa Visit, 10 Jan 2014 10 A.M

Billa Visit, 11 Jan 2014 10 A.M

Billa Visit, 17 Jan 2014 10 A.M

Billa Visit, 18 Jan 2014 10 A.M

Billa Visit, 24 Jan 2014 10 A.M

Billa Visit, 25 Jan 2014 10 A.M

SQL FIDDLE LINK

Community
  • 1
  • 1
Billa
  • 5,226
  • 23
  • 61
  • 105
  • 2
    Note that threads involving RIGHT JOINs are vanishingly rare in SO. (currently LEFT JOIN = 50,506 hits vs RIGHT JOIN = 2,337) - just sayin' – Strawberry Nov 29 '13 at 13:47
  • @Strawberry, fine. This query was taken based on other question. I am not worrying about LEFT or RIGHT :) Want some solution to find those dates – Billa Nov 29 '13 at 13:56
  • 1
    M$SQL's not my thing but, FWIW, I always try to construct a (pseudo-normalized) materialized view (or even just a plain, vanilla VIEW) out of an EAV before trying to get anything useful out of it. Oh, and BTW, I get the impression that some contributors to SO find images of data off-putting. Consider providing proper DDLs instead. – Strawberry Nov 29 '13 at 14:14
  • Since this question is still unanswered, I posted a solution below. If this is not exactly what you need, I could modify this based on your feedback. – laylarenee Dec 04 '13 at 15:31
  • New answer added, with fully-functional SQL FIDDLE. I observed in your SQL fiddle that your query is in the wrong pane. If you move it to the right pane, it does run, but returns nothing. – laylarenee Dec 04 '13 at 17:34
  • Billa, Is your only request to get the "Expected Result" show above? or is there more you need? – laylarenee Dec 05 '13 at 14:10
  • @Billa i need a small help – Niranjan N Raju Oct 10 '15 at 12:51

5 Answers5

15

Your first step is to get your event start dates with each event, and the repeat interval, to do this you can use:

SELECT  EventID = e.ID, 
        e.Name, 
        StartDateTime = DATEADD(SECOND, rs.Meta_Value, '19700101'),
        RepeatInterval = ri.Meta_Value
FROM    dbo.Events e
        INNER JOIN dbo.Events_Meta rs
            ON rs.Event_ID = e.ID
            AND rs.Meta_Key = 'repeat_start'
        INNER JOIN dbo.Events_Meta ri
            ON ri.Event_ID = e.ID
            AND ri.Meta_Key = 'repeat_interval_' + CAST(e.ID AS VARCHAR(10));

This gives:

EventID | Name         | StartDateTime       | RepeatInterval
--------+--------------+---------------------+-----------------
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800
   1    | Billa Vist   | 2014-01-04 18:00:00 |     604800

To get this to repeat you will need a numbers table to cross join to, if you don't have one there are a number of ways to generate one on the fly, for simplicity reasons I will use:

WITH Numbers AS
(   SELECT  Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
)
SELECT  Number
FROM    Numbers;

For further reading, Aaron Bertrand has done some in depth comparisons ways of generating sequential lists of numbers:

If we limit our numbers table to only 0 - 5, and only look at the first event, cross joining the two will give:

EventID | Name         | StartDateTime       | RepeatInterval | Number
--------+--------------+---------------------+----------------+---------
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    0
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    1
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    2
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    3
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    4
   1    | Billa Vist   | 2014-01-03 10:00:00 |     604800     |    5

Then you can get your occurance by adding RepeatInterval * Number to the event start time:

DECLARE @EndDate DATETIME = '20140130';

WITH EventData AS
(   SELECT  EventID = e.ID, 
            e.Name, 
            StartDateTime = DATEADD(SECOND, rs.Meta_Value, '19700101'),
            RepeatInterval = ri.Meta_Value
    FROM    dbo.Events e
            INNER JOIN dbo.Events_Meta rs
                ON rs.Event_ID = e.ID
                AND rs.Meta_Key = 'repeat_start'
            INNER JOIN dbo.Events_Meta ri
                ON ri.Event_ID = e.ID
                AND ri.Meta_Key = 'repeat_interval_' + CAST(rs.ID AS VARCHAR(10))
), Numbers AS
(   SELECT  Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
)
SELECT  e.EventID,
        e.Name,
        EventDate = DATEADD(SECOND, n.Number * e.RepeatInterval, e.StartDateTime)
FROM    EventData e
        CROSS JOIN Numbers n
WHERE   DATEADD(SECOND, n.Number * e.RepeatInterval, e.StartDateTime) < @EndDate
ORDER BY e.EventID, EventDate;

This gives your expected output:

EVENTID | NAME          | EVENTDATE
--------+---------------+--------------------------------
   1    | Billa Vist    | January, 03 2014 10:00:00+0000
   1    | Billa Vist    | January, 04 2014 18:00:00+0000
   1    | Billa Vist    | January, 10 2014 10:00:00+0000
   1    | Billa Vist    | January, 11 2014 18:00:00+0000
   1    | Billa Vist    | January, 17 2014 10:00:00+0000
   1    | Billa Vist    | January, 18 2014 18:00:00+0000
   1    | Billa Vist    | January, 24 2014 10:00:00+0000
   1    | Billa Vist    | January, 25 2014 18:00:00+0000

Example on SQL Fiddle


I think the schema you have is questionable though, the join on:

Meta_Key = 'repeat_interval_' + CAST(rs.ID AS VARCHAR(10))

is flimsy at best. I think you would be much better off storing the start date and repeat interval associated with it together:

CREATE TABLE dbo.Events_Meta
(       ID INT IDENTITY(1, 1) NOT NULL,
        Event_ID INT NOT NULL,
        StartDateTime DATETIME2 NOT NULL,
        IntervalRepeat INT NULL, -- NULLABLE FOR SINGLE EVENTS
        RepeatEndDate DATETIME2 NULL, -- NULLABLE FOR EVENTS THAT NEVER END
    CONSTRAINT PK_Events_Meta__ID PRIMARY KEY (ID),
    CONSTRAINT FK_Events_Meta__Event_ID FOREIGN KEY (Event_ID) REFERENCES dbo.Events (ID)
);

This would simplify your data to:

EventID | StartDateTime       | RepeatInterval | RepeatEndDate
--------+---------------------+----------------+---------------
   1    | 2014-01-03 10:00:00 |    604800      |     NULL
   1    | 2014-01-04 18:00:00 |    604800      |     NULL

It also allows you to add an end date to your repeat, i.e. if you only want it to repeat for one week. This then your query simlifies to:

DECLARE @EndDate DATETIME = '20140130';
WITH Numbers AS
(   SELECT  Number = ROW_NUMBER() OVER(ORDER BY a.object_id) - 1
    FROM    sys.all_objects a
)
SELECT  e.ID,
        e.Name,
        EventDate = DATEADD(SECOND, n.Number * em.IntervalRepeat, em.StartDateTime) 
FROM    Events e
        INNER JOIN Events_Meta em
            ON em.Event_ID = e.ID
        CROSS JOIN Numbers n
WHERE   DATEADD(SECOND, n.Number * em.IntervalRepeat, em.StartDateTime) <= @EndDate
AND (   DATEADD(SECOND, n.Number * em.IntervalRepeat, em.StartDateTime) <= em.RepeatEndDate 
    OR  em.RepeatEndDate IS NULL
    )
ORDER BY EventDate;

Example on SQL Fiddle


I won't give you my full schema for how I have achieved this in the past, but I will give a very cut down example, from which you can hopefully build your own. I will only add an example for an event that occurs weekly on Mon-Fri:

enter image description here

In the above ER RepeatEvent stores the basic information for the recurring event, then depending on the repeat type (Daily, weekly, monthly) one or more of the other tables is populated. In example of a weekly event, it would store all the days of the week that it repeats in in the table RepeatDay. If this needed to be limited to only certain months, you could store these months in RepeatMonth, and so on.

Then using a calendar table you can get all the possible dates after the first date, and limit these to only those dates that match the day of the week/month of the year etc:

WITH RepeatingEvents AS
(   SELECT  e.Name,
            re.StartDateTime,
            re.EndDateTime,
            re.TimesToRepeat,
            RepeatEventDate = CAST(c.DateKey AS DATETIME) + CAST(re.StartTime AS DATETIME),
            RepeatNumber = ROW_NUMBER() OVER(PARTITION BY re.RepeatEventID ORDER BY c.Datekey)
    FROM    dbo.Event e
            INNER JOIN dbo.RepeatEvent re
                ON e.EventID = re.EventID
            INNER JOIN dbo.RepeatType rt
                ON rt.RepeatTypeID = re.RepeatTypeID
            INNER JOIN dbo.Calendar c
                ON c.DateKey >= re.StartDate
            INNER JOIN dbo.RepeatDayOfWeek rdw
                ON rdw.RepeatEventID = re.RepeatEventID
                AND rdw.DayNumberOfWeek = c.DayNumberOfWeek
    WHERE   rt.Name = 'Weekly'
)
SELECT  Name, StartDateTime, RepeatEventDate, RepeatNumber
FROM    RepeatingEvents
WHERE   (TimesToRepeat IS NULL OR RepeatNumber <= TimesToRepeat)
AND     (EndDateTime IS NULL OR RepeatEventDate <= EndDateTime);

Example on SQL Fiddle

This is only a very basic representation of how I implemented it, for instance I actually used entirely views any query for the repeating data so that any event with no entries in RepeatDayOfWeek would be assumed to repeat every day, rather than never. Along with all the other detail in this and other answers, you should hopefully have more than enough to get you started.

Community
  • 1
  • 1
GarethD
  • 68,045
  • 10
  • 83
  • 123
  • Going through your answer. In bounty i said `Creating a booking management system where i need to shedule a doctor visit like every monday 10 AM to 12 A.M and 2 P.M to 6 P.M Other possiblities are every day between, or some days between some time` , now i am analyzing how my design will fit for all scenarios. I also had a look at [this component](http://www.daypilot.org/calendar-tutorial-recurring-events.html), they handled different, but the business scenario (UI) is atmost same for me – Billa Dec 04 '13 at 14:19
  • 1
    There are a number of ways to approach this and depending on your exact requirements you may adopt a different approach, however the key point in the answer is that once you have the start date, and the repeat interval, you need to cross join to a sequential numbers table to get all instances of the event. – GarethD Dec 04 '13 at 14:32
  • Great. I agree on it. Could you please help me to correct the current database design. Will it be perfect for the given UI ? or do i need to add some more fields in event meta data table? – Billa Dec 04 '13 at 14:47
  • The current system would not work perfectly for the UI you have put in the question, there are many complicated factors in recurring events, such as rather than events that occur every n days/weeks/months, you also have events that occur on the first/last x of y, e.g. last friday of the month, first working day of the month etc. It soon gets quite complicated trying to account for all scenarios. I have done 2 systems similar to this, in one I used XML to store the data using SSRS schedule data as a template, in the other I used tables, neither of which were simple. – GarethD Dec 06 '13 at 13:06
  • 2
    In summary, I don't think there is a right or a wrong way to go about it, it all depends on what you need and what you are comfortable with and I doubt anyone on SO will design your system for you, ultimately it is a Q&A site not a consultancy service. I would love to help out more, but it would be a massive answer if I posted the schema I have used with accompanying documentation, which I would have to write as it doesn't exist, it would also take me a couple of hours to fully document, which is a little too long for free work! – GarethD Dec 06 '13 at 13:12
  • Could you please share some shema design for your table based apporoach? in some blog or github.com, so i get some idea on it to proceed. :) I updated the simplified UI diagram – Billa Dec 06 '13 at 16:07
  • @Billa - you've already received a whole bunch of information on this page and in this post about numerous ways to proceed. You've already been given so much... just use it and modify it to your exact needs. Everyone who posted here has given a lot of info on the concepts behind their approaches. – gloomy.penguin Dec 06 '13 at 21:32
  • Excellent!!!. Hats off to you :) I could able to offer only 100, as I could not increase the bounty now :( – Billa Dec 09 '13 at 15:17
  • Interesting... `WITH Dates AS ( SELECT DateKey = DATEADD(DAY, spt.Number, '20131201') FROM Master..spt_values spt WHERE spt.Type = 'P' )` calander construction is limited to `2048` rows and restricting to 2048 days. What if they need more ? – Murali Murugesan Dec 10 '13 at 15:30
  • @Murali then I suggest they use the method in my answer with sys.all_objects or read the articles I linked to about generating a sequential list of numbers! As I said numerous times I am not offering a full solution, merely guidance. – GarethD Dec 10 '13 at 15:42
  • @GarethD, Everything looks so good. But I am failing to implement the actual requirement with the final schema. :(. I need to get the schedule for a person on a given date. The person will do a hair cut, every 45 mins , only week days during 10 A.M to 1 P.M only. 4 hair cuts for every day. Tried version of [SQLFiddle](http://sqlfiddle.com/#!3/37476/1). Not sure what is the problem :( it shows only 1 record – Billa Feb 19 '14 at 12:28
  • 1
    Basically what you are trying to do is multiple repeats, which it isn't set up to do, you are trying to repeat every 45 minutes and every day. You also have an end date, which is why there is only one row. The schema I gave you was not set up to deal with things repeating multiple times per day, You can get around this by creating 4 repeat events for the event (at 10:00, 10:45, 11:30 and 12:15), then repeating these 4 daily. [Demo on SQL Fiddle](http://sqlfiddle.com/#!3/ccdcc/1) – GarethD Feb 19 '14 at 12:53
  • @GarethD, What is `RepeatInterval` and `TimesToRepeat` in RepeatEvent table? It has value 1 & NULL not sure, what is the impact of those 2 fields? Kindly advice – Billa Feb 19 '14 at 14:22
  • `TimesToRepeat` indicates how many times an event should repeat, i.e. if something was only due to go on for 10 days, it would only repeat the event 10 times if you set `TimesToRepeat = 10. `RepeatInterval` is something I did not include in the workings of the example. It is basically there to store the gap between repeating intervals, i.e. repeating every 2 weeks would require this to be 2. – GarethD Feb 19 '14 at 15:04
  • @GarethD, somehow i reduced adding more rows for every 45 mins. I mean i added two more columns `StartTime` & `EndTime` in Event Table and the final query is working. Please check [Demo](http://sqlfiddle.com/#!3/fe27d/1) . I used temp table approach. But the problem is, populating it only for one event `SELECT @CURRENT_TIME = StartTime, @START_TIME = StartTime, @END_TIME = EndTime, @DURATION = Duration FROM [Event] where EventID = 1`. Check my query. Is there way we can populate all events ? – Billa Feb 21 '14 at 10:39
  • Do you have any idea on this too? http://stackoverflow.com/questions/24609263/get-records-based-on-current-date-and-configured-data , I am not able to make this like schedule :( – Billa Jul 07 '14 at 15:00
3

The following will generate events based on StartEvent and MEta description with a CTE.

Change the values for MaxDate and MaxEvents according to parameters values.

declare @MaxDate datetime = convert(datetime,'12/2/2014', 101);
declare @MaxEvents integer=  200;

; With
    -- number generator by power of 2
    n2(n) as ( select 1 as n union all select 1),
    n4(n) as ( select 1 from n2 t1 cross join n2 t2 ),
    n16(n) as ( select 1 from n4 t1 cross join n4 t2 ),
    n256(n) as ( select 1 from n16 t1 cross join n16 t2 ),
    n65k(n) as ( select 1 from n256 t1 cross join n256 t2 ),
   Numbers (n) as (select row_number() over( order by n) from n65k ),

    -- Start of events 
    StartEvents as 
    ( SELECT 1 as EventNo, EV.Name, EM.ID, EM.Event_Id, EM.Meta_key, dateAdd(second,EM.meta_value,convert(datetime,'01/01/1970', 101)) as EventDate
        FROM events AS EV
        INNER JOIN events_meta  EM 
          ON EM.event_id = EV.id
          AND EM.meta_key = 'repeat_start'),
    -- Repeating events N times
    NextEvents AS
    ( SELECT Numbers.N+1 asEventNo, StartEvents.Name, EM.ID, EM.Event_Id, EM.Meta_key, dateAdd(second,EM.meta_value*Numbers.n,StartEvents.EventDate) as EventDate
        FROM StartEvents 
        INNER JOIN  events_meta EM 
            ON EM.event_id = StartEvents.event_id
            AND  EM.meta_key = 'repeat_interval_'+ ltrim(rtrim(str(StartEvents.ID )))
            AND ((1391040000- EM.meta_value ) % EM.meta_value) = 0 
     cross join Numbers 
     -- not to overflow (dateadd parameter is int type)
     Where Numbers.N < 3000
    )
   -- startEvents union nextEvents
  select EventNo, Name, Meta_key, EventDate
  FROM (
        Select * from StartEvents
        union all select * from NextEvents ) AllEvents
  where EventDate < @MaxDate
   and  EventNo < @MaxEvents
        order by ID ;
ARA
  • 1,296
  • 10
  • 18
1

One way of accomplishing this is by using a loop and inserting a record into a temp table. Then you can simply select from your temp table. In the example below I saved off both the unixtimestamp value as well as that value converted to datetime.

declare @enddate bigint, @intervalFactor int, @rowresult int

set @enddate = 1391040000

create table #Results
(
  eventid int,
  eventdate bigint,
  eventdatedate datetime
)

set @rowresult = 1
set @intervalFactor = 0

WHILE (@rowresult > 0)
BEGIN
  Insert #Results (eventid, eventdate, eventdatedate)
  Select events.id, date.meta_value + (intrvl.meta_value * @intervalFactor)
        ,DATEADD(ss,date.meta_value + (intrvl.meta_value * @intervalFactor), CAST('1970-01-01 00:00:00' AS datetime))
      from events
      inner join events_meta date
        on events.id = date.event_id
        AND date.meta_key = 'repeat_start'
      inner join events_meta intrvl
        on events.id = intrvl.event_id
        and intrvl.meta_key = 'repeat_interval_'+ CAST(date.id as Varchar(100))
  where ((@enddate - date.meta_value ) % intrvl.meta_value) >= 0
  and date.meta_value + (intrvl.meta_value * @intervalFactor) <= @enddate


  set @rowresult = @@rowcount
  set @intervalFactor = @intervalFactor + 1

END  

select * from #Results

Another possible solution for this problem would to utilize a recursive CTE.

Michael
  • 599
  • 6
  • 11
  • Your code works. missing other event data, please check the updated question and your result http://www.sqlfiddle.com/#!3/fdfe4 – Billa Dec 04 '13 at 11:51
  • added a bounty for this – Billa Dec 04 '13 at 12:05
  • My code sample has been updated and should give your expected results. I had an incorrect join from events table to the aliased date table. I was joining to date.id instead of date.event_id. – Michael Dec 04 '13 at 13:26
1

This will do it!

WITH mycte AS
(
    SELECT A.ID, A.Name, A.StartDate, A.StartDate AS [IntervalDate], A.Interval, A.[repeat_startID], A.[repeat_intervalID]
    FROM (
            -- this is your provided query
            -- can you run this derived table only and make sure it return what you expect?
        SELECT
             EV.*
            ,EM1.id AS [repeat_startID]
            ,EM2.id AS [repeat_intervalID]
            -- I convert to datetime becuase Im more familiar with datatype=time manipulations
            ,DATEADD(SECOND,EM1.meta_value,'1970-01-01') AS [StartDate]
            ,EM2.meta_value AS [Interval]
        FROM [EVENTS] AS EV
            -- I used inner joins, please modify that as needed.
            INNER JOIN [EVENTS_META] AS EM1 ON EM1.meta_key = 'repeat_start' AND EM1.event_id = EV.id
            INNER JOIN [EVENTS_META] AS EM2 ON EM2.meta_key = 'repeat_interval_'+ CAST(EM1.id as Varchar(100))
    ) AS A
    UNION ALL
    SELECT  ID, Name, StartDate, DATEADD(SECOND,Interval,[IntervalDate]), Interval, [repeat_startID], [repeat_intervalID]
    FROM    mycte   
    WHERE   DATEADD(SECOND,1,[IntervalDate]) < '2014-01-30 00:00:00.000' -- this is your epoch timestamp
)
SELECT * FROM mycte 
-- it is unclear if the "cutoff" date is for the Last Interval's Start Date or the next one
-- examining the results shows there are 2 records after your"cutoff" date
-- add a WHERE statement to fix this if needed?
-- WHERE [IntervalDate] < '2014-01-30 00:00:00.000' -- this is your epoch timestamp
ORDER BY [repeat_startID], StartDate;

-- produces: (Column #4 is what you are interested in)
1   Billy Visit 2014-01-03 10:00:00.000 2014-01-03 10:00:00.000 604800  1   2
1   Billy Visit 2014-01-03 10:00:00.000 2014-01-10 10:00:00.000 604800  1   2
1   Billy Visit 2014-01-03 10:00:00.000 2014-01-17 10:00:00.000 604800  1   2
1   Billy Visit 2014-01-03 10:00:00.000 2014-01-24 10:00:00.000 604800  1   2
1   Billy Visit 2014-01-03 10:00:00.000 2014-01-31 10:00:00.000 604800  1   2 -- occurs after '2014-01-30 00:00:00.000'
1   Billy Visit 2014-01-04 18:00:00.000 2014-01-04 18:00:00.000 604800  3   4
1   Billy Visit 2014-01-04 18:00:00.000 2014-01-11 18:00:00.000 604800  3   4
1   Billy Visit 2014-01-04 18:00:00.000 2014-01-18 18:00:00.000 604800  3   4
1   Billy Visit 2014-01-04 18:00:00.000 2014-01-25 18:00:00.000 604800  3   4
1   Billy Visit 2014-01-04 18:00:00.000 2014-02-01 18:00:00.000 604800  3   4 -- occurs after '2014-01-30 00:00:00.000'
laylarenee
  • 3,276
  • 7
  • 32
  • 40
0

This code works as desired, all field names match your SQL FIDDLE, output will need tweaked very slightly to show your custom time format. I could not find a default conversion for your format.

http://www.sqlfiddle.com/#!3/057fe/1

This solution uses CTE to recursively create new rows of data, each one starting at a point in time and then being an increment of the "Interval" until it meets the end date. Once this cte table is created, it requires a simple query to extract your data.

; -- previous statement must terminate w/ semicolon
WITH mycte AS
(
    SELECT A.ID, A.Name, A.StartDate, A.StartDate AS [IntervalDate], A.[Interval]
    FROM (
            -- this is your provided query
            SELECT EV.*
                -- I added two derived fields to simplify the recursion process.
                ,DATEADD(SECOND,EM1.meta_value,'1970-01-01') AS StartDate
                ,EM2.meta_value AS [Interval]
            FROM events AS EV
            RIGHT JOIN events_meta AS EM1 ON EM1.event_id = EV.id
            RIGHT JOIN events_meta AS EM2 ON EM2.meta_key = 'repeat_interval_'+ CAST(EM1.id as Varchar(100))
            WHERE EM1.meta_key = 'repeat_start'
    ) AS A
    UNION ALL
    SELECT  ID, Name, StartDate, DATEADD(SECOND,Interval,[IntervalDate]), [Interval]
    FROM    mycte   
    WHERE   DATEADD(SECOND,1,[IntervalDate]) < '2014-01-30 00:00:00.000' -- this is your epoch timestamp
)
SELECT Name + ', ' + CONVERT(VARCHAR,[IntervalDate],113)-- format your custom date as needed.
FROM mycte 
WHERE [IntervalDate] < '2014-01-30 00:00:00.000' -- this is your epoch timestamp
ORDER BY StartDate
OPTION (Maxrecursion 1000); -- default is 100 if not stated
laylarenee
  • 3,276
  • 7
  • 32
  • 40