MS SQL Table of CRON Future Runs - sql-server

I have a need to create a table/view containing a full and complete list of future CRON executions for a period of time, e.g. from 12 months ago to 12 months in the future.
My source data is in MS SQL 2012 and contains the following sample information;
TASK SCHEDULE SCHEDULESTART SCHEDULEEND
T1 0 0 0 ? * MON 2015-04-08 16:15:09.557 2015-04-20 00:00:00.000
T2 0 0 0 ? * MON 2015-05-22 15:56:48.140 2015-07-27 00:00:00.000
T3 0 0/56 * * * ? 2015-06-25 10:17:07.387 2015-06-25 15:00:00.000
T4 0 10/15 21 3,19 5-9 ? 2015-06-25 10:18:48.077 2015-08-28 10:17:15.000
Unfortunately as MS SQL doesn't support/contain a JVM, I'm limited (I think) to programmatically breaking this out into it's components parts.
I've managed to break out he parts of the expression with the following;
;WITH cte (SCHEDULE,SCHEDULESTART,SCHEDULEEND,SCHED_Attributes)
AS
(
SELECT SCHEDULE,SCHEDULESTART,SCHEDULEEND,
CONVERT(XML,'<Product><Attribute>'
+ REPLACE([SCHEDULE],' ', '</Attribute><Attribute>')
+ '</Attribute></Product>') AS SCHED_Attributes
FROM USCH_TASK
)
SELECT
SCHEDULE,SCHEDULESTART,SCHEDULEEND,
SCHED_Attributes.value('/Product[1]/Attribute[1]','varchar(25)') AS sched_seconds,
SCHED_Attributes.value('/Product[1]/Attribute[2]','varchar(25)') AS sched_minutes,
SCHED_Attributes.value('/Product[1]/Attribute[3]','varchar(25)') AS sched_hours,
SCHED_Attributes.value('/Product[1]/Attribute[4]','varchar(25)') AS sched_day_of_month,
SCHED_Attributes.value('/Product[1]/Attribute[5]','varchar(25)') AS sched_month,
SCHED_Attributes.value('/Product[1]/Attribute[6]','varchar(25)') AS sched_day_of_week,
SCHED_Attributes.value('/Product[1]/Attribute[7]','varchar(25)') AS sched_year
from cte
This results in (for example)
sched_seconds sched_minutes sched_hours sched_day_of_month sched_month sched_day_of_week sched_year
0 0 0 ? * MON NULL
0 0 0 ? * MON NULL
0 0/56 * * * ? NULL
0 10/15 21 3,19 5-9 ? NULL
Main thrust of this question is then how to handle the component parts of this, * and ? are easy enough, ranges (e.g. 5-9 or MON-THU) are pretty OK, but am struggling with how to determine where have specific dates/months (e.g. 3,19) or more complex configurations (such as the last example above or days of month ="1-3,6-7,15")
CASE
WHEN CHARINDEX('*',Prod_Attributes.value('/Product[1]/Attribute[6]','varchar(25)')) > 0 THEN 'Y'
WHEN CHARINDEX('?',Prod_Attributes.value('/Product[1]/Attribute[6]','varchar(25)')) > 0 THEN 'Y'
WHEN CHARINDEX('MON',Prod_Attributes.value('/Product[1]/Attribute[6]','varchar(25)')) > 0 THEN 'Y'
WHEN CHARINDEX('SUN-TUE',Prod_Attributes.value('/Product[1]/Attribute[6]','varchar(25)')) > 0 THEN 'Y'
WHEN CHARINDEX('SUN-WED',Prod_Attributes.value('/Product[1]/Attribute[6]','varchar(25)')) > 0 THEN 'Y'
WHEN CHARINDEX('SUN-THU',Prod_Attributes.value('/Product[1]/Attribute[6]','varchar(25)')) > 0 THEN 'Y'
WHEN CHARINDEX('SUN-FRI',Prod_Attributes.value('/Product[1]/Attribute[6]','varchar(25)')) > 0 THEN 'Y'
WHEN CHARINDEX('SUN-SAT',Prod_Attributes.value('/Product[1]/Attribute[6]','varchar(25)')) > 0 THEN 'Y'
ELSE 'N'
END as DOWMon
However this approach wouldn't work for day 1 of the month as the code
WHEN CHARINDEX('1',Prod_Attributes.value('/Product[1]/Attribute[4]','varchar(25)')) > 0 THEN 'Y'
would also find value 10 through 19, 21 and 31!
Any tips or tricks are gratefully received!
Andy

Related

SQL Server query problem. example is in excel sheet picture

Please see the following pic and i want to convert this formula in SQL Server.
in excel sheet
M N
15 1 0
16 3 1
17 5 2
18 8 4
19 9 4
N= IF(M16-M15<=1,N15,M16-M15-1+N15
Please see the screenshot for reference:
As per your tags, this can be done with LAG and then doing a running total.
For each row, first calculate the difference in M from the previous row (using LAG) - I call this Dif_Last_M. This mirrors the 'M24-M23' part of your formula.
If Dif_Last_M is <= 1, add 0 to the running total (effectively making the running total the same as for the previous row)
Else if Dif_Last_M is > 1, add (Dif_Last_M minus 1) to the running total
Here is the code assuming your source table is called #Temp and has an ID (sorting value)
WITH M_info AS
(SELECT ID, M, (M - LAG(M, 1) OVER (ORDER BY ID)) AS Dif_Last_M
FROM #Temp
)
SELECT ID,
M,
SUM(CASE WHEN Dif_Last_M > 1 THEN Dif_Last_M - 1 ELSE 0 END) OVER (ORDER BY ID) AS N
FROM M_info;
And here are the results
ID M N
1 1 0
2 3 1
3 5 2
4 8 4
5 9 4
6 12 6
7 13 6
Here is a db<>fiddle with the above. It also includes additional queries showing
The result from the CTE
The values used in the running total
Note that while it possible to do this with recursive CTEs, they tend to have performance problems (they are loops, fundamentally). Soit is better (performance-wise) to avoid recursive CTEs if possible.

excel match year and month in array

I have an array of dates in column a that i would like to match against on year and month.
A B C D E F G H I J
1 date name Name March April May June July August September
2 13-04-2016 Lars Lars 0 0 0 0 0 0 0
3 04-03-2016 Brian Brian 0 0 0 0 0 0 0
4 01-01-2016 Lars Erik 0 0 0 0 0 0 0
5 10-06-2016 Erik Knut 0 0 0 0 0 0 0
6 31-07-2016 Erik Soren 0 0 0 0 0 0 0
I have tried with $A:$A;"="&DATE(YEAR(TODAY());3;""); where ;3; is the month of march. It evaluates to 0 on all accounts.
So how to adapt to make it count the number of dates matching the Year and Month (D2) for Lars (C2) in A:A?
Anyone.
One way to do this is to convert the date to text, then evaluate that in your formula.
Logic:
If Monthname(Date) = Top Row, then 1, else 0
Formula (placed in cell D2):
=if(text($A1,"mmmm")=D$1,1,0)
I have used the relative references for clicking and dragging.
Put this in D2 (and adapt as needed)
=IF(DATE(YEAR(TODAY()),3,1)=DATE(YEAR(A3),MONTH(A3),1),1,0)
=IF( --Start the if
DATE(YEAR(TODAY()),3,1) -- Current year, 3rd month, 1st day
= --Equals (for if statement)
DATE(YEAR(A3),MONTH(A3),1) -- Year & month from Cell A3 & 1st day
,1,0) -- Print '1' if true else print '0'

total days in Arrears calculation

guys i have problem with one old SP which calculates total days late when the costumer is late with the payments of an instalment
it goes like this:
#total days paid# #1st inst days due# #2nd inst days due# #total days#
---------------------------------------------------------------------------
---------------------------------------------------------------------------
0 1 0 1
0 2 0 2
0 3 0 3
0 4 0 4
0 30 0 30
0 31 1 31
0 32 2 32
32 0 3 35
so the procedure calculates (total days paid) + max of the days due
0+32 =32
32+3 =35
etc
and makes mistakes whenever the costumer is latemore then 30 days
its should always increment by 1 and not overlap the calculations
can anyone think of a quick way to fix this without over writhing the whole thing
so you have an existing formula for calculating #total days#, if you can locate the final place where that is returned, it could be a formula or a field name, let's call that (...) because we don't know what it is here, you can change it to
(...) + CASE WHEN (...) >= 30 THEN 1 ELSE 0 END AS '#total days#'

Group and sum with SQL Server

I am a begginer using this kind of query in SQL Server and I have a big table similar as I'm showing, the trouble that I have is that I don't know how to group and sum at the same time, I need to sum the SUP with every SIG with the code
CODE SIG SUP
R501004002 BCO 30
R501004002 BCO 31.27
R501004008 BCO 34.09
R501004008 BCO 35.94
R501004003 MET 42
R501004020 RIP 42.5
R501004039 BCO 47.44
R501004020 RIP 68.56
The result that I want to show is something like this
CODE BCO MET RIP
R501004002 61.27 0 0
R501004003 0 42 0
R501004008 70.03 0 0
R501004020 0 0 111.06
R501004039 47.44 0 0
I group the code
Assuming only 3 sigs...
SELECT code
, sum(case when sig = 'BCO' then sup else 0 end) as BCO
, sum(case when sig = 'MET' then sup else 0 end) as MET
, sum(case when sig = 'RIP' then sup else 0 end) as RIP
FROM tableName
GROUP BY code
otherwise use a dynamic pivot as exampled here

Total field in Crosstab query in SQL Server 2008

I have got this result with the answer given by bluefeet
Equipt BSL AQ
TFP 3 2
TM 1 0
VCB 18 6
VCD 5 8
Query script was
SELECT Equipt, [BSL] AS BSL, [AQ] AS AQ
FROM
(
SELECT Equipt, Shed
FROM PunctualityMain WHERE Date >= '4/1/2012' AND Date <= '4/30/2012' AND classification = 'Loco'
) x
PIVOT
(
COUNT(Shed)
FOR Shed IN ([BSL], [AQ])
) p
Can it be possible to added one total field the above script like access crosstab
Equipt BSL AQ TTL
TFP 3 2 5
TM 1 0 1
VCB 18 6 24
VCD 5 8 13
You should be able to add the Totals field by including a new column:
SELECT Equipt, [BSL] AS BSL, [AQ] AS AQ, ([BSL] + [AQ]) as TTL
FROM
(
SELECT Equipt, Shed
FROM PunctualityMain
WHERE Date >= '4/1/2012' AND Date <= '4/30/2012'
AND classification = 'Loco'
) x
PIVOT
(
COUNT(Shed)
FOR Shed IN ([BSL], [AQ])
) p

Resources