How to create a 2nd temp table in SQL - sql

I have such a situation. I basically need to put my whole code into a second temp table(?) to be able to select from it. The code inside works just fine I just cannot understand how to basically create a bigger temp table that will absorb the first one and the previous select and later allow select one more time.
This is what I have right now
WITH t AS
( Select
p.[PDITM#], l.SGDWHS, p.PDCHN, p.PDWEDT, Sum(p.PDQSLD) AS 'Sum',
case when p.PDCHN = 'DH' then p.PDQSLD else 0 end as DHSLD,
case when p.PDCHN = 'WM' then p.PDQSLD else 0 end as WMSLD,
case when p.PDCHN = 'MJ' then p.PDQSLD else 0 end as MJSLD,
case when p.PDCHN = 'BJ' then p.PDQSLD else 0 end as BJSLD
FROM [Repit].[LEVYDTA].[POSDTLM] p
LEFT OUTER JOIN [Repit].[LEVYDTA].[LDSSGEN] l
ON p.[PDAGY]=l.[SGAGY] AND p.[PDCHN] = l.[SGCHN] AND p.[PDSTR] = l.[SGSTR]
WHERE p.[PDQSLD] > 0 AND p.[PDAGY] != 15
AND l.[SGDWHS] IN (01, 21, 30, 40, 02)
AND CONVERT(DATE, CONVERT(CHAR(8), p.PDWEDT )) = cast(DATEADD(dd, DATEPART(DW,GETDATE())*-1, GETDATE()) as date)
GROUP BY p.[PDITM#], l.[SGDWHS], p.[PDCHN], p.[PDWEDT], p.[PDQSLD]
)
select t.[PDITM#] as [PDITM#],
t.SGDWHS as [SGDWHS],
SUM(t.Sum) as [PDQSLD],
SUM(t.DHSLD) AS [DHSLD],
SUM(t.WMSLD) AS [WMSLD],
SUM(t.MJSLD) AS [MJSLD],
SUM(t.BJSLD) AS [BJSLD],
SUM(t.Sum) - (SUM(t.DHSLD) + SUM(t.WMSLD) + SUM(t.MJSLD) + SUM(t.BJSLD)) as OTHRSLD
from t
GROUP BY t.PDITM#, t.SGDWHS
ORDER BY t.PDITM#, t.SGDWHS
I need to select such fields from the upper table
SELECT t.PDITM#, t.SGDWHS,
CAST((t.DHSLD/t.Sum) * 100 as DECIMAL (18,2)) AS 'DHPCT',
CAST((t.WMSLD/t.Sum) * 100 as DECIMAL (18,2)) AS 'WMPCT',
CAST((t.MJSLD/t.Sum) * 100 as DECIMAL (18,2)) AS 'MJPCT',
CAST((t.BJSLD/t.Sum) * 100 as DECIMAL (18,2)) AS 'BJPCT',
CAST(((t.Sum - ( t.DHSLD + t.WMSLD + t.MJSLD + t.BJSLD))/t.Sum) * 100 as DECIMAL (18,2)) AS 'OTHRPCT'
FROM second temp table
I will appreciate if someone can let me know how it may be possible. I have spent time trying to figure it out by myself, but there is not much info when you need to make multiple temp tables and selecting them.

If you're using MSSQL, this might be what you're trying to do?
-- Drop temp table if already present
DROP TABLE IF EXISTS #temp_main
SELECT
p.[PDITM#]
, l.SGDWHS
, p.PDCHN
, p.PDWEDT
, SUM(p.PDQSLD) AS [Sum_PDQSLD]
, case when p.PDCHN = 'DH' then p.PDQSLD else 0 end as [DHSLD]
, case when p.PDCHN = 'WM' then p.PDQSLD else 0 end as [WMSLD]
, case when p.PDCHN = 'MJ' then p.PDQSLD else 0 end as [MJSLD]
, case when p.PDCHN = 'BJ' then p.PDQSLD else 0 end as [BJSLD]
-- Select data into temp table.
INTO #temp_main
FROM [Repit].[LEVYDTA].[POSDTLM] AS p
LEFT JOIN [Repit].[LEVYDTA].[LDSSGEN] AS l
ON p.[PDAGY]=l.[SGAGY] AND p.[PDCHN] = l.[SGCHN] AND p.[PDSTR] = l.[SGSTR]
WHERE p.[PDQSLD] > 0 AND p.[PDAGY] != 15 AND l.[SGDWHS] IN (01, 21, 30, 40, 02)
AND CONVERT(DATE, CONVERT(CHAR(8), p.PDWEDT)) = cast(DATEADD(dd, DATEPART(DW,GETDATE())*-1, GETDATE()) as date)
GROUP BY
p.[PDITM#]
, l.[SGDWHS]
, p.[PDCHN]
, p.[PDWEDT]
, p.[PDQSLD]
-- Table 1
SELECT
t.[PDITM#]
, t.SGDWHS
, SUM(t.Sum_PDQSLD) as [PDQSLD]
, SUM(t.DHSLD) AS [DHSLD]
, SUM(t.WMSLD) AS [WMSLD]
, SUM(t.MJSLD) AS [MJSLD]
, SUM(t.BJSLD) AS [BJSLD]
, SUM(t.Sum_PDQSLD) - (SUM(t.DHSLD) + SUM(t.WMSLD) + SUM(t.MJSLD) + SUM(t.BJSLD)) as [OTHRSLD]
from #temp_main AS t -- Temp table
GROUP BY t.[PDITM#], t.SGDWHS
ORDER BY t.[PDITM#], t.SGDWHS
-- Table 2
SELECT
t.[PDITM#]
, t.SGDWHS
, CAST((t.DHSLD/t2.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [DHPCT]
, CAST((t.WMSLD/t.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [WMPCT]
, CAST((t.MJSLD/t.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [MJPCT]
, CAST((t.BJSLD/t.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [BJPCT]
, CAST(((t.Sum_PDQSLD - (t.DHSLD + t.WMSLD + t.MJSLD + t.BJSLD))/t.Sum_PDQSLD) * 100 as DECIMAL (18,2)) AS [OTHRPCT]
FROM #temp_main AS t -- Temp table
ORDER BY t.[PDITM#], t.SGDWHS
-- Drop table once complete.
DROP TABLE #table_main

Related

Sql agent job last run status

I have N jobs with M steps in each, that could change any time(Add/delete some steps). Jobs have different schedule to run. I want a query to get last run status, job id, job name of each job. Is it right way to do this scenario by (Job outcome) ?
This is the query I use (a little tuned) to check job status. This variation will select the last job outcome for each job.
SELECT
JobName = J.name,
H.*
FROM
msdb.dbo.sysjobs AS J
CROSS APPLY (
SELECT TOP 1
JobName = J.name,
StepNumber = T.step_id,
StepName = T.step_name,
StepStatus = CASE T.run_status
WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Succeeded'
WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Canceled'
ELSE 'Running' END,
ExecutedAt = msdb.dbo.agent_datetime(T.run_date, T.run_time),
ExecutingHours = ((T.run_duration/10000 * 3600 + (T.run_duration/100) % 100 * 60 + T.run_duration % 100 + 31 ) / 60) / 60,
ExecutingMinutes = ((T.run_duration/10000 * 3600 + (T.run_duration/100) % 100 * 60 + T.run_duration % 100 + 31 ) / 60) % 60,
Message = T.message
FROM
msdb.dbo.sysjobhistory AS T
WHERE
T.job_id = J.job_id
ORDER BY
T.instance_id DESC) AS H
ORDER BY
J.name
If you change the TOP 1 for TOP 2, then you will also see the last step executed, aside from the job outcome.
You can not get everything in a single query and need more research. For e.g., to know Job execution information you can try the following query.
SELECT
[sJOB].[job_id] AS [JobID]
, [sJOB].[name] AS [JobName]
, CASE
WHEN [sJOBH].[run_date] IS NULL OR [sJOBH].[run_time] IS NULL THEN NULL
ELSE CAST(
CAST([sJOBH].[run_date] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJOBH].[run_time] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END AS [LastRunDateTime]
, CASE [sJOBH].[run_status]
WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Succeeded'
WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Canceled'
WHEN 4 THEN 'Running' -- In Progress
END AS [LastRunStatus]
, STUFF(
STUFF(RIGHT('000000' + CAST([sJOBH].[run_duration] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS [LastRunDuration (HH:MM:SS)]
, [sJOBH].[message] AS [LastRunStatusMessage]
, CASE [sJOBSCH].[NextRunDate]
WHEN 0 THEN NULL
ELSE CAST(
CAST([sJOBSCH].[NextRunDate] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJOBSCH].[NextRunTime] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END AS [NextRunDateTime]
FROM
[msdb].[dbo].[sysjobs] AS [sJOB]
LEFT JOIN (
SELECT
[job_id]
, MIN([next_run_date]) AS [NextRunDate]
, MIN([next_run_time]) AS [NextRunTime]
FROM [msdb].[dbo].[sysjobschedules]
GROUP BY [job_id]
) AS [sJOBSCH]
ON [sJOB].[job_id] = [sJOBSCH].[job_id]
LEFT JOIN (
SELECT
[job_id]
, [run_date]
, [run_time]
, [run_status]
, [run_duration]
, [message]
, ROW_NUMBER() OVER (
PARTITION BY [job_id]
ORDER BY [run_date] DESC, [run_time] DESC
) AS RowNumber
FROM [msdb].[dbo].[sysjobhistory]
WHERE [step_id] = 0
) AS [sJOBH]
ON [sJOB].[job_id] = [sJOBH].[job_id]
AND [sJOBH].[RowNumber] = 1
ORDER BY [JobName]
You can get and learn in details - Here and Here

need to convert sql time from decimal to hours

I have this code:
cast( DateDiff( MINUTE, S.PlannedStartDateTime, S.PlannedEndDateTime) as decimal (12,6)) / 60 else null end) BasicHours
which brings back the date time as decimal i.e. 31.416666, but this really needs to be 31hr 25mins
How can my code display the correct date format?
Yet another option.
Example
Declare #YourTable table (id int,StartTime datetime,EndTime datetime)
Insert Into #YourTable values
(1,'2017-01-01 20:30:15','2017-01-05 22:58:35'),
(2,'2017-01-01 09:00:00','2017-01-01 17:00:00'),
(3,'2017-01-01 09:00:00','2017-01-01 09:05:00')
Select A.ID
,Duration = concat(Seconds/3600,'hr ',Seconds%3600/60,'mins')
From #YourTable A
Cross Apply (values (DateDiff(SECOND,StartTime,EndTime))) B (Seconds)
Returns
ID Duration
1 98hr 28mins
2 8hr 0mins
3 0hr 5mins
EDIT if you don't want the CROSS APPLY
Select A.ID
,Duration = concat(DateDiff(SECOND,StartTime,EndTime)/3600,'hr ',DateDiff(SECOND,StartTime,EndTime)%3600/60,'mins')
From #YourTable A
One Should Note:, there is a limitation ... the max value of an INT (or 2,147,483,647). So provided your span does not exceed:
Years Months Days Hours Minutes Seconds
68 0 19 3 14 7
This is my version of Itzik Ben Gan's DATEDIFFPARTS function
CREATE FUNCTION dbo.tfn_DateDiffParts
/* =======================================================================================================
04/06/2017 JL, Created.
Code based off of a similar function created by Itzik Ben-Gan.
(http://sqlmag.com/sql-server/how-compute-date-and-time-difference-parts)
======================================================================================================= */
(
#dt1 AS DATETIME2(7),
#dt2 AS DATETIME2(7)
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN
SELECT
DateDiffParts = CONCAT(
CAST(V.yy AS VARCHAR(10)) + L.yy,
CAST(V.mm AS VARCHAR(10)) + L.mm,
CAST(V.dd AS VARCHAR(10)) + L.dd,
CAST(V.hh AS VARCHAR(10)) + L.hh,
CAST(V.mi AS VARCHAR(10)) + L.mi,
CAST(V.ss AS VARCHAR(10)) + L.ss
)
FROM
( VALUES (
CASE WHEN #dt1 > #dt2 THEN #dt2 ELSE #dt1 END,
CASE WHEN #dt1 > #dt2 THEN #dt1 ELSE #dt2 END
)
) D (dt1, dt2)
CROSS APPLY ( VALUES (
CAST(D.dt1 AS TIME),
CAST(D.dt2 AS TIME),
DATEDIFF(yy, D.dt1, D.dt2),
DATEDIFF(mm, D.dt1, D.dt2),
DATEDIFF(dd, D.dt1, D.dt2)
)
) A1 (t1, t2, yydiff, mmdiff, dddiff)
CROSS APPLY ( VALUES (
CASE WHEN DATEADD(yy, A1.yydiff, D.dt1) > D.dt2 THEN 1 ELSE 0 END,
CASE WHEN DATEADD(mm, A1.mmdiff, D.dt1) > D.dt2 THEN 1 ELSE 0 END,
CASE WHEN DATEADD(dd, A1.dddiff, D.dt1) > D.dt2 THEN 1 ELSE 0 END
)
) A2 (subyy, submm, subdd)
CROSS APPLY ( VALUES (
CAST(86400000000000 AS BIGINT) * A2.subdd
+ (CAST(1000000000 AS BIGINT) * DATEDIFF(ss, '00:00', A1.t2) + DATEPART(ns, A1.t2))
- (CAST(1000000000 AS BIGINT) * DATEDIFF(ss, '00:00', A1.t1) + DATEPART(ns, A1.t1))
)
) A3 (nsdiff)
CROSS APPLY ( VALUES (
A1.yydiff - A2.subyy,
(A1.mmdiff - A2.submm) % 12,
DATEDIFF(DAY, DATEADD(mm, A1.mmdiff - A2.submm,D.dt1), D.dt2) - A2.subdd,
A3.nsdiff / CAST(3600000000000 AS BIGINT),
A3.nsdiff / CAST(60000000000 AS BIGINT) % 60,
CAST(A3.nsdiff / 1000000000.0 % 60.0 AS DECIMAL(9,1))
)
) V (yy, mm, dd, hh, mi, ss)
CROSS APPLY ( VALUES (
CASE
WHEN V.yy > 1 THEN ' years, '
WHEN V.yy > 0 THEN ' year, '
END,
CASE
WHEN V.mm > 1 THEN ' months, '
WHEN V.mm > 0 THEN ' month, '
WHEN V.yy > 0 THEN ' months, '
END,
CASE
WHEN V.dd > 1 THEN ' days, '
WHEN V.dd > 0 THEN ' day, '
WHEN V.yy > 0 OR V.mm > 0 THEN ' days, '
END,
CASE
WHEN V.hh > 1 THEN ' hours, '
WHEN V.hh > 0 THEN ' hour, '
WHEN V.yy > 0 OR V.mm > 0 OR V.dd > 0 THEN ' hours, '
END,
CASE
WHEN V.mi > 1 THEN ' mins, '
WHEN V.mi > 0 THEN ' min, '
WHEN V.yy > 0 OR V.mm > 0 OR V.dd > 0 OR V.hh > 0 THEN ' mins, '
END,
CASE
WHEN V.ss > 1 THEN ' secs'
WHEN V.ss > 0 THEN ' sec'
WHEN V.yy > 0 OR V.mm > 0 OR V.dd > 0 OR V.hh > 0 OR V.mi > 0 THEN ' secs'
END
)
) L (yy, mm, dd, hh, mi, ss);
GO
Sample query...
SELECT
ddp.DateDiffParts
FROM
dbo.tfn_DateDiffParts('2017-06-01 08:22:11.12345', '2017-06-02 11:30:25.32145') ddp;
And the function output...
DateDiffParts
--------------------------------------------------------------------------------------------------------
1 day, 3 hours, 8 mins, 14.2 secs
you can use below query to get your result -
select CAST (CONCAT( datediff(HH,'2017-09-05 21:55:00','2017-09-07 08:16:00') , '.' , 60- datediff(MINUTE,'2017-09-05 21:55:00','2017-09-07 08:16:00')%60) as decimal (12,6))
--OUTPUT
35.390000

joining select statements?

I would like to do a inner join in my query but I don´t know how to summarize my two select statements into one query.
This is the first query:
select
Machine
, EventDefinition
, Duration
, sum(Duration) over (partition by 1) As Total
, Duration/sum(Duration) over (partition by 1)*100 AS Distribution
,case when EventCategory < 0.05 Then 'NOT INCL' ELSE 'OK' END AS Under3Min
from (
Select
SystemName AS Machine
, EventDefinition
, EventDate
, EventStartDateTime
, IsNull(EventEndDateTime, GETDATE()) as EventEndDateTime
, Sum(cast(EventEndDateTime - EventStartDateTime as float))*24 as Duration
,Sum(case when CustomEvent = 'without Stop' then cast(EventEndDateTime - EventStartDateTime as float)*24 else 0 end) as EventCategory
FROM tDataCategory
WHERE EventDate >= #StartDateTime
AND EventDate <= #EndDateTime
AND SystemName = '201'
Group BY SystemName, eventdefinition, eventstartdatetime, eventenddatetime, EventDefinition, EventDate, CustomEvent
) as t
WHERE CustomEvent <> 'without Stop'
OR (CustomEvent = 'without Stop' AND t.EventCategory >=0.05)
group by EventDefinition
, Duration
,Machine
,EventCategory
output:
and my second query:
SELECT DataValue = case when Prod = 0 then 0 else ISNULL(100.0 / Prod * Scrap, 0) end,
Value = GoodUnits/TheoreticalUnits *100,
FROM (
Select intervaldate as DateValue, intervalDateWeek as Datum, tsystem.Name as Name, ProductName as Product, teamname as Team,
SUM(case when IssueName in ('A1', 'A2') then calculationUnitsInitial else 0 end) as Scrap,
Sum(case when IssueName = 'Prod' then calculationUnitsInitial else 0 end) as Prod,
SUM(GoodUnits)
As GoodUnits,
SUM(TheoreticalUnits) As TheoreticalUnits,
from tCount inner join tsystem ON tCount.systemid = tsystem.id
where IntervalDate >= dateadd(wk, datediff(wk, 1, getdate()), 0)
and IntervalDate <= dateadd(wk, datediff(wk, 0, getdate()), 0)
AND ((DATEPART(dw, IntervalDate) + ##DATEFIRST) % 7) NOT IN (0,1)
and tsystem.Name = '201'
group by intervaldate, tsystem.Name, intervaldateweek, ProductName, teamname
) as s
output:
I tried it to add in my query two select statements. But if I do this the output is wrong. I really don´t know how I should join this two queries.
I would like to do then this calculation: Distribution * (1 - Value)
Distribution from the first query and Value from the second query
I assume the first and second result set has to be joined based on A.Machine=B.Name
Try like this,
SELECT A.Distribution * (1 - B.Value)
FROM (
SELECT Machine
,EventDefinition
,Duration
,sum(Duration) OVER (PARTITION BY 1) AS Total
,Duration / sum(Duration) OVER (PARTITION BY 1) * 100 AS Distribution
,CASE
WHEN EventCategory < 0.05
THEN 'NOT INCL'
ELSE 'OK'
END AS Under3Min
FROM (
SELECT SystemName AS Machine
,EventDefinition
,EventDate
,EventStartDateTime
,IsNull(EventEndDateTime, GETDATE()) AS EventEndDateTime
,Sum(cast(EventEndDateTime - EventStartDateTime AS FLOAT)) * 24 AS Duration
,Sum(CASE
WHEN CustomEvent = 'without Stop'
THEN cast(EventEndDateTime - EventStartDateTime AS FLOAT) * 24
ELSE 0
END) AS EventCategory
FROM tDataCategory
WHERE EventDate >= #StartDateTime
AND EventDate <= #EndDateTime
AND SystemName = '201'
GROUP BY SystemName
,eventdefinition
,eventstartdatetime
,eventenddatetime
,EventDefinition
,EventDate
,CustomEvent
) AS t
WHERE CustomEvent <> 'without Stop'
OR (
CustomEvent = 'without Stop'
AND t.EventCategory >= 0.05
)
GROUP BY EventDefinition
,Duration
,Machine
,EventCategory
) A
INNER JOIN (
SELECT DataValue = CASE
WHEN Prod = 0
THEN 0
ELSE ISNULL(100.0 / Prod * Scrap, 0)
END
,Value = GoodUnits / TheoreticalUnits * 100
,NAME
FROM (
SELECT intervaldate AS DateValue
,intervalDateWeek AS Datum
,tsystem.NAME AS NAME
,ProductName AS Product
,teamname AS Team
,SUM(CASE
WHEN IssueName IN (
'A1'
,'A2'
)
THEN calculationUnitsInitial
ELSE 0
END) AS Scrap
,Sum(CASE
WHEN IssueName = 'Prod'
THEN calculationUnitsInitial
ELSE 0
END) AS Prod
,SUM(GoodUnits) AS GoodUnits
,SUM(TheoreticalUnits) AS TheoreticalUnits
,
FROM tCount
INNER JOIN tsystem ON tCount.systemid = tsystem.id
WHERE IntervalDate >= dateadd(wk, datediff(wk, 1, getdate()), 0)
AND IntervalDate <= dateadd(wk, datediff(wk, 0, getdate()), 0)
AND ((DATEPART(dw, IntervalDate) + ##DATEFIRST) % 7) NOT IN (
0
,1
)
AND tsystem.NAME = '201'
GROUP BY intervaldate
,tsystem.NAME
,intervaldateweek
,ProductName
,teamname
) AS s
) B ON A.Machine = B.NAME

How to breakdown time policy life period by beginning and end of the months

Picture. Need to be like that
I need to break down each policy life period by months. From the beginning of the policy till the end of that month, then from the beginning till the end of the next month and for each of this time period need to calculate the number of days, so then I can calculate earned premium for each policy.
Please see the picture what do I need to achieve.
[DECLARE #EarnedToDate datetime ='2016-06-30'
;WITH Cte_Policies AS
(
SELECT
PolicyNumber
,TransactionEffectiveDate
,TransactionExpirationDate
,WrittenPremium
,DATEDIFF(DAY,TransactionEffectiveDate,TransactionExpirationDate) AS TotalDays
,CASE
WHEN TransactionEffectiveDate> #EarnedToDate THEN 0 --Policy not yet in effect
WHEN TransactionExpirationDate< #EarnedToDate THEN DATEDIFF(DAY,TransactionEffectiveDate,TransactionExpirationDate)
ELSE DATEDIFF(DAY,TransactionEffectiveDate,#EarnedToDate)
END AS EarnedDays
,CASE
WHEN TransactionEffectiveDate > #EarnedToDate THEN DATEDIFF(DAY,TransactionEffectiveDate,TransactionExpirationDate)
WHEN TransactionExpirationDate < #EarnedToDate THEN 0 -- Policy completed
ELSE DATEDIFF(DAY,#EarnedToDate,TransactionExpirationDate)
END AS UnearnedDays
FROM ##TempTable1
)
SELECT PolicyNumber,
TransactionEffectiveDate as TransactionEffectiveDate,
TransactionExpirationDate as TransactionExpirationDate
--WrittenPremium/TotalDays AS DayPremium,
,SUM(CASE WHEN EarnedDays = 0 THEN 0 ELSE WrittenPremium/TotalDays * EarnedDays END) AS EarnedPremium
,SUM(CASE WHEN UnearnedDays = 0 THEN 0 ELSE WrittenPremium/TotalDays * UnearnedDays END) AS UnearnedPremium
FROM
Cte_Policies where PolicyNumber ='PACA1000238-02'
GROUP BY
TransactionEffectiveDate
,TransactionExpirationDate
--,WrittenPremium/TotalDays
,PolicyNumber][1]
My original snippet answered your question on Twitter, but the following code snippet takes the first one a bit further and provides exactly the result set specified on your question here on StackOverflow...
; WITH Earned_to_date AS (
SELECT Cast('2016-07-01' AS DATE) AS Earned_to_date
), policy_data AS (
SELECT
policy_number
, Cast(text_Effective AS DATE) AS TransactionEffectiveDate
, Cast(text_Expiration AS DATE) AS TransactionExpirationDate
, policy_premium
FROM (VALUES
('p1', '1993-01-01', '1994-12-31', 940.00)
, ('p3', '2011-12-01', '2012-05-31', 485.00)
, ('p5', '2011-12-16', '2012-05-15', 485.00)
, ('p7', '2015-12-16', '2016-11-15', 485.00)
) AS z (policy_number, text_Effective
, text_Expiration, policy_premium)
), digits AS (
SELECT digit
FROM (VALUES (0), (1), (2), (3), (4)
, (5), (6), (7), (8), (9)) AS z2 (digit)
), numbers AS (
SELECT 1000 * d4.digit + 100 * d3.digit + 10 * d2.digit + d1.digit AS number
FROM digits AS d1
CROSS JOIN digits AS d2
CROSS JOIN digits AS d3
CROSS JOIN digits AS d4
), calendar AS (
SELECT
DateAdd(month, number, '1753-01-01') AS month_of
, DateAdd(month, number, '1753-02-01') AS month_after
FROM numbers
), policy_dates AS (
SELECT
policy_number
, CASE
WHEN month_of < TransactionEffectiveDate THEN TransactionEffectiveDate
ELSE month_of
END AS StartRiskMonth
, CASE
WHEN TransactionExpirationDate < month_after THEN TransactionExpirationDate
WHEN Earned_to_date.Earned_to_date < month_after THEN Earned_to_date
ELSE month_after
END AS EndRiskMonth
, DateDiff(day, TransactionEffectiveDate, TransactionExpirationDate) AS policy_days
, policy_premium
FROM policy_data
JOIN calendar
ON (policy_data.TransactionEffectiveDate < calendar.month_after
AND calendar.month_of < policy_data.TransactionExpirationDate)
CROSS JOIN Earned_to_date
WHERE month_of < Earned_to_date
)
SELECT policy_number, StartRiskMonth, EndRiskMonth
, DateDiff(day, StartRiskMonth, EndRiskMonth) AS DaysInMonth
, policy_premium * DateDiff(day, StartRiskMonth, EndRiskMonth) / policy_days
FROM policy_dates
ORDER BY policy_number, StartRiskMonth
As I thought from your tweet, this is pretty simple to code but it takes a bit of work to understand.
WITH raw_data AS (
SELECT
Cast(text_TransactionEffectiveDate AS DATE) AS TransactionEffectiveDate
, Cast(text_TransactionExpirationDate AS DATE) AS TransactionExpirationDate
FROM (VALUES
('1953-01-15', '1992-02-23')
, ('2012-08-12', '2012-08-26')
) AS z (text_TransactionEffectiveDate, text_TransactionExpirationDate )
), policy_dates AS (
SELECT
raw_data.*
, DateAdd(month, DateDiff(month, '1753-01-01', TransactionEffectiveDate), '1753-01-01') AS Policy_Start
, DateAdd(month, DateDiff(month, '1753-01-01', TransactionExpirationDate), '1753-02-01') AS Policy_Expired
FROM raw_data
)
SELECT DateDiff(day, Policy_start, Policy_Expired) AS Policy_days, *
FROM policy_dates
This is a computation that is common in the insurance field. The trick lies in computing the beginning of the Effective Month, and the beginning of the expiration month (after the policy has ended). The trick is that at one point a month later than the others (1753-02-01) is used.
-PatP
Add a CTE or two that breaks the policy effective and expiration dates into distinct months, then re-use your existing code/CTE
Be sure to review all boundary conditions for EarnedDays and UnearnedDays and make sure they line up with your business rules
DECLARE #EarnedToDate DATETIME
SET #EarnedToDate = '2016-06-30'
DECLARE #tblPolicies TABLE
(
PolicyNumber VARCHAR(100)
, PolicyEffectiveDate DATETIME
, PolicyExpirationDate DATETIME
, WP MONEY --WrittenPremium
)
DECLARE #tblPolicyMonths TABLE
(
PolicyNumber VARCHAR(100),
MonthStart DATETIME,
MonthEnd DATETIME
)
DECLARE #CurPos INT
SET #CurPos = 1
WHILE #CurPos < 4000
BEGIN
--Create a bunch of policies
INSERT INTO #tblPolicies
SELECT 'P' + CONVERT(varchar, #CurPos), DATEADD(d, #CurPos, GETDATE()), DATEADD(YY, 1, DATEADD(d, #CurPos, GETDATE())), #CurPos
SET #CurPos = #CurPos + 1
END
DECLARE #LastPolicyDate DATETIME
SET #LastPolicyDate = (SELECT MAX(PolicyExpirationDate) FROM #tblPolicies)
;WITH Cte_All_Dates AS
(
SELECT MIN(PolicyEffectiveDate) DateValue
FROM #tblPolicies
UNION ALL
SELECT DateValue + 1
FROM Cte_All_Dates
WHERE DateValue + 1 < = #LastPolicyDate
)
INSERT INTO #tblPolicyMonths
SELECT P.PolicyNumber
,MIN(DateValue)
,MAX(DateValue)
FROM Cte_All_Dates PD
INNER JOIN #tblPolicies P
ON CONVERT(DATE, PD.DateValue) BETWEEN P.PolicyEffectiveDate AND P.PolicyExpirationDate
GROUP BY P.PolicyNumber
, DATEPART(MM, DateValue)
, DATEPART(YY, DateValue)
OPTION (MAXRECURSION 32767);
SELECT
P.PolicyNumber
,CONVERT(DATE, MonthStart) As StartRiskMonth
,CONVERT(DATE, MonthEnd) AS EndRiskMonth
,WP as WrittenPremium
,DATEDIFF(DAY,MonthStart,MonthEnd)+1 AS TotalDays
,CASE
WHEN MonthStart > #EarnedToDate THEN 0 --Policy not yet in effect
WHEN MonthEnd < #EarnedToDate THEN DATEDIFF(DAY,MonthStart,MonthEnd)+1
ELSE DATEDIFF(DAY,MonthStart,#EarnedToDate)+1
END AS EarnedDays
,CASE
WHEN MonthStart > #EarnedToDate THEN DATEDIFF(DAY,MonthStart,MonthEnd)+1
WHEN MonthEnd < #EarnedToDate THEN 0 -- Policy completed
ELSE DATEDIFF(DAY,#EarnedToDate,MonthEnd)
END AS UnearnedDays
, #EarnedToDate AS 'EarnedToDate'
FROM #tblPolicyMonths PM
INNER JOIN #tblPolicies P
ON PM.PolicyNumber = P.PolicyNumber
ORDER BY PolicyNumber, MonthStart, MonthEnd

SQL - How to find currently running job steps through TSQL

I am writing a query to find currently running job in SQL (I know we can view it in Job Active Monitor, but I've a need to do in TSQL). Though I can query sysjobactivity table to find currently running job, it's nowhere telling what job step is running (because my job might have more than 1 step).
Query I used:
SELECT s.name AS [JOB_NAME],
'' AS [STEP_ID],
'' AS STEP_NAME,
'Processing' AS STATUS,
sja.run_requested_date AS START_TIME,
null AS END_DATE,
convert(varchar, (getdate() - sja.run_requested_date), 8) AS Duration
FROM sysjobactivity sja, sysjobs s
WHERE sja.job_id = s.job_id
AND sja.run_requested_date > getdate() - 1
AND sja.stop_execution_date IS NULL
Please help me finding the step ID & Step name in which the job is currently progressing.
I think below script help to get SQL Jobs with current execution step, try this
msdb.dbo.sp_help_job #execution_status = 1
DECLARE #StepCount INT
SELECT #StepCount = COUNT(1)
FROM msdb.dbo.sysjobsteps
WHERE job_id = '0523333-5C24-1526-8391-AA84749345666' --JobID
SELECT
[JobName]
,[JobStepID]
,[JobStepName]
,[JobStepStatus]
,[RunDateTime]
,[RunDuration]
FROM
(
SELECT
j.[name] AS [JobName]
,Jh.[step_id] AS [JobStepID]
,jh.[step_name] AS [JobStepName]
,CASE
WHEN jh.[run_status] = 0 THEN 'Failed'
WHEN jh.[run_status] = 1 THEN 'Succeeded'
WHEN jh.[run_status] = 2 THEN 'Retry (step only)'
WHEN jh.[run_status] = 3 THEN 'Canceled'
WHEN jh.[run_status] = 4 THEN 'In-progress message'
WHEN jh.[run_status] = 5 THEN 'Unknown'
ELSE 'N/A'
END AS [JobStepStatus]
,msdb.dbo.agent_datetime(run_date, run_time) AS [RunDateTime]
,CAST(jh.[run_duration]/10000 AS VARCHAR) + ':' + CAST(jh.[run_duration]/100%100 AS VARCHAR) + ':' + CAST(jh.[run_duration]%100 AS VARCHAR) AS [RunDuration]
,ROW_NUMBER() OVER
(
PARTITION BY jh.[run_date]
ORDER BY jh.[run_date] DESC, jh.[run_time] DESC
) AS [RowNumber]
FROM
msdb.[dbo].[sysjobhistory] jh
INNER JOIN msdb.[dbo].[sysjobs] j
ON jh.[job_id] = j.[job_id]
WHERE
j.[name] = 'ProcessCubes' --Job Name
AND jh.[step_id] > 0
AND CAST(RTRIM(run_date) AS DATE) = CAST(GETDATE() AS DATE) --Current Date
) A
WHERE
[RowNumber] <= #StepCount
AND [JobStepStatus] = 'Failed'
Try this:
SELECT distinct
cast([sJOB].[job_id] as varchar(max)) AS execution_id
, [sJSTP].[step_name] AS executable_name
, [sJOB].[name] AS package_name
, CASE [sJSTP].[run_date]
WHEN 0 THEN NULL
ELSE
CAST(
CAST([sJSTP].[run_date] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJSTP].[run_time] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END AS start_time,
dateadd(ss, run_duration, CASE [sJSTP].[run_date]
WHEN 0 THEN NULL
ELSE
CAST(
CAST([sJSTP].[run_date] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJSTP].[run_time] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END) end_time
-- , [sJSTP].[run_duration] [looptijd in minuten]
, CASE [sJSTP].[run_status]
WHEN 0 THEN 'Failed'
WHEN 1 THEN 'Success'
WHEN 2 THEN 'Retry'
WHEN 3 THEN 'Cancelled'
WHEN 5 THEN 'Unknown'
END AS execution_result_description
FROM
[msdb].[dbo].[sysjobhistory] AS [sJSTP]
INNER JOIN [msdb].[dbo].[sysjobs] AS [sJOB]
ON [sJSTP].[job_id] = [sJOB].[job_id]
inner join [msdb].[dbo].[sysjobsteps] steps
ON [sJSTP].[job_id] = [steps].[job_id]
where [sJSTP].[run_date] <> 0
and CASE [sJSTP].[run_date]
WHEN 0 THEN NULL
ELSE
CAST(
CAST([sJSTP].[run_date] AS CHAR(8))
+ ' '
+ STUFF(
STUFF(RIGHT('000000' + CAST([sJSTP].[run_time] AS VARCHAR(6)), 6)
, 3, 0, ':')
, 6, 0, ':')
AS DATETIME)
END between dateadd(hh, -20, getdate()) and getdate()
and [sJSTP].[step_name] not in ('(Job outcome)')
order by start_time desc
Additionally I use this query to see step result from a running SSIS job. However, this only shows you the finished steps, not the running ones. I still have to find an SQL to see the currently running step and merge it with this one.
select distinct
cast(e.execution_id as varchar(max)),
e.executable_name,
e.package_name,
CONVERT(datetime, es.start_time) AS start_time
, CONVERT(datetime, es.end_time) AS end_time
, datediff(mi, es.start_time, es.end_time) [running time]
, case es.execution_result
when 0 then 'Success'
when 1 then 'Failed'
when 2 then 'Completion'
when 3 then 'Cancelled'
else cast(es.execution_result as varchar(max)) end as execution_result_description
from ssisdb.catalog.executables e
left join ssisdb.catalog.executable_statistics es
on e.executable_id = es.executable_id
and e.execution_id = es.execution_id
order by 6 desc