T SQL дней или часов или минут, оставшихся до указанного c дня и времени начала расписания - PullRequest
0 голосов
/ 16 февраля 2020

У меня есть XML, который имеет несколько расписаний. Мне нужна помощь, чтобы показать с текущего дня (пример: понедельник, 14:00:03), сколько дней, часов или минут осталось до указанного c расписания [Sched 1 AT] или [Sched 2 AT] времени начала и дня [Sched 1 Weekdays] или [Sched 1 Weekdays] в отдельном столбце [TimeLeft]. У меня есть расписание:

  1. ежедневно
  2. раз в неделю в воскресенье или субботу
  3. раз в 2 недели в воскресенье или субботу

My XML и запрос:

create table MyTable (Roles XML)
insert into MyTable values
('<registered guid="{B40F5E54-21D0-4EDB-B636-B2F9EE30CCDE}">
  <schedule tz="Local" start="2007-11-01 00:00:00">
      <trigger type="MonthlyByWeek" exact="False" at="18:05:00" weeks="2" weekdays="6" description="Every 2nd Saturday" />
      <trigger type="MonthlyByWeek" exact="False" at="00:05:00" weeks="2" weekdays="0" description="Every 2nd Sunday" />
    <modifier type="Network" />
  </schedule>
</registered>

<registered guid="{A4465325-926A-48FA-B11E-D6E486D76D93}">
  <schedule tz="Local" start="2009-11-11 00:00:00">
	<trigger type="Weekly" exact="True" at="00:05:00" frequency="1" weekdays="0" description="Weekly on Sunday" />
	<trigger type="Weekly" exact="True" at="04:05:00" frequency="1" weekdays="0" description="Weekly on Sunday" />
	<modifier type="Network" />
  </schedule>
</registered>

<registered guid="{3DE26049-74E7-4FE3-9E47-CF022A6F7923}">
  <schedule tz="Local" start="2011-11-11 00:00:00">
      <trigger type="Weekly" exact="True" at="00:07:30" frequency="1" weekdays="1, 2, 3, 4, 5, 6" description="Daily" />
      <modifier type="Network" />
  </schedule>
</registered>')

SELECT T.Schedule.query('.') AS Schedule,
       CASE	
		WHEN T.Schedule.value('(schedule/trigger/@type)[1]', 'nvarchar(100)') IS NULL
		THEN 'None'
		ELSE T.Schedule.value('(schedule/trigger/@type)[1]', 'nvarchar(100)')		
		END [Sched 1 When],
	   CASE
		WHEN T.Schedule.value('(schedule/trigger/@at)[1]', 'nvarchar(100)') IS NULL
		THEN 'None'
		ELSE T.Schedule.value('(schedule/trigger/@at)[1]', 'nvarchar(100)')		
		END [Sched 1 AT],
       -- Week Start Sunday
       -- Sunday = 0
       -- Monday = 1
       -- Tuesday = 2
       -- Wednesday = 3
       -- Thursday = 4
       -- Friday = 5
       -- Saturday = 6
       CASE	
		WHEN T.Schedule.value('(schedule/trigger/@frequency)[1]', 'nvarchar(100)') LIKE '%1%'
		THEN 'Once'
		WHEN T.Schedule.value('(schedule/trigger/@frequency)[1]', 'nvarchar(100)') IS NULL
		THEN 'None'
		ELSE 'Unknown'
	   END [Sched 1 Frequency],
       CASE	
		WHEN T.Schedule.value('(schedule/trigger/@description)[1]', 'nvarchar(100)') IS NULL
		THEN 'None'
		ELSE T.Schedule.value('(schedule/trigger/@description)[1]', 'nvarchar(100)')
	   END [Sched 1 Description],	   
       CASE	
		WHEN T.Schedule.value('(schedule/trigger/@weekdays)[1]', 'nvarchar(100)') = '1, 2, 3, 4, 5, 6'
		THEN 'Mon, Tue, Wend, Thu, Fri, Sat'
		WHEN T.Schedule.value('(schedule/trigger/@weekdays)[1]', 'nvarchar(100)') LIKE '%0%'
		THEN 'Sun'
		WHEN T.Schedule.value('(schedule/trigger/@weekdays)[1]', 'nvarchar(100)') LIKE '%6%'
		THEN 'Sat'
		ELSE 'Unknown'
	   END [Sched 1 Weekdays],	   
       CASE	
		WHEN T.Schedule.value('(schedule/trigger/@type)[2]', 'nvarchar(100)') IS NULL
		THEN 'None'
		ELSE T.Schedule.value('(schedule/trigger/@type)[2]', 'nvarchar(100)')		
		END [Sched 2 When],
	   CASE
		WHEN T.Schedule.value('(schedule/trigger/@at)[2]', 'nvarchar(100)') IS NULL
		THEN 'None'
		ELSE T.Schedule.value('(schedule/trigger/@at)[2]', 'nvarchar(100)')		
		END [Sched 2 AT],	   
       CASE	
		WHEN T.Schedule.value('(schedule/trigger/@frequency)[2]', 'nvarchar(100)') LIKE '%1%'
		THEN 'Once'
		WHEN T.Schedule.value('(schedule/trigger/@frequency)[2]', 'nvarchar(100)') IS NULL
		THEN 'None'
		ELSE 'Unknown'
	   END [Sched 2 Frequency],
       CASE	
		WHEN T.Schedule.value('(schedule/trigger/@description)[2]', 'nvarchar(100)') IS NULL
		THEN 'None'
		ELSE T.Schedule.value('(schedule/trigger/@description)[2]', 'nvarchar(100)')
	   END [Sched 2 Description],	   
       CASE	
		WHEN T.Schedule.value('(schedule/trigger/@weekdays)[2]', 'nvarchar(100)') = '1, 2, 3, 4, 5, 6'
		THEN 'Mon, Tue, Wend, Thu, Fri, Sat'
		WHEN T.Schedule.value('(schedule/trigger/@weekdays)[2]', 'nvarchar(100)') LIKE '%0%'
		THEN 'Sun'
		WHEN T.Schedule.value('(schedule/trigger/@weekdays)[2]', 'nvarchar(100)') LIKE '%6%'
		THEN 'Sat'
		WHEN T.Schedule.value('(schedule/trigger/@weekdays)[2]', 'nvarchar(100)') IS NULL
		THEN 'None'		
		ELSE 'Unknown'
	   END [Sched 2 Weekdays]
FROM 
( SELECT CAST(Roles AS XML) as [State] from Mytable
) x
CROSS APPLY x.State.nodes('/registered') AS T(Schedule)

1 Ответ

1 голос
/ 16 февраля 2020
declare @checkdatetime datetime = '20200216 10:00:00';

select *, datediff(minute, @checkdatetime, o.execdatetime) as minutes_till_next_execution
from
(
    select *,
    row_number() over(partition by Scheduleguid, TrigAt /*?*/ order by execdatetime) as execrownum
    from
    (
        select 
            sch.*,
            --possible execution datetime   
            dateadd(day, d.n,
                dateadd(month, isnull(m.n, 0),
                --datetimefromparts(.....)
                cast(cast(year(@checkdatetime) as varchar(20)) + right('00'+cast(month(@checkdatetime) as varchar(20)), 2) + '01 ' + TrigAt  as datetime)
            )) as execdatetime
        from 
        --shred xml
        (
            select
                T.Schedule.value('(@guid)[1]', 'uniqueidentifier') AS Scheduleguid,
                dense_rank() over(order by T.Schedule) as ScheduleOrdinal, --position
                S.Trig.value('(@type)[1]', 'nvarchar(100)') as TrigType,
                S.Trig.value('(@at)[1]', 'nvarchar(100)') as TrigAt,
                S.Trig.value('(@weeks)[1]', 'tinyint') as MonthWeekFrequency,
                S.Trig.value('(@frequency)[1]', 'tinyint') as TrigFrequency,
                S.Trig.value('(@description)[1]', 'nvarchar(100)') as TrigDescription,
                S.Trig.value('(@weekdays)[1]', 'varchar(20)') as TrigWeekdays,
                cast(ltrim(rtrim(ss.value)) as tinyint) as triggerweekday
            FROM Mytable as x
            cross apply x.Roles.nodes('./registered[position() <= 100]') AS T(Schedule) --position() to filter schedules in xml (first 2, 3, 100 schedules etc)
            cross apply T.Schedule.nodes('./schedule/trigger') AS S(Trig)
            cross apply string_split(S.Trig.value('(@weekdays)[1]', 'varchar(20)'), ',') as ss --split weekdays of trigger
        ) as sch
        --lazy brute force
        --days
        cross apply
        (
            --31 values for days in a month
            select top (31) row_number() over(order by (select null)) as n
            from 
            (values(0), (0), (0), (0), (0), (0)) as num1(n) 
            cross join
            (values(0), (0), (0), (0), (0), (0)) as num2(n) 
        ) as d
        --months
        outer apply
        (
            --2 values for current and next month
            select n
            from (values(0), (1)) as num(n) 
            where sch.MonthWeekFrequency is not null
        ) as m
    ) as ex
    where 1=1
    -- execution dates which are eq or greater than @check
    and @checkdatetime  <= ex.execdatetime
    -- execution dates of the same trigweekday
    and ex.triggerweekday = datepart(weekday, dateadd(day, @@datefirst, ex.execdatetime))-1
    --execution dates on the same week number
    and 
    (
      ex.MonthWeekFrequency is null
      or
      ex.MonthWeekFrequency = datediff(week, dateadd(month, datediff(month, '20200101', ex.execdatetime), '20200101'), ex.execdatetime) +1
    )
) as o
where o.execrownum = 1 --...the very next execution
order by ScheduleOrdinal, TrigAt;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...