Split datetime SQL Server 2008 - tsql

I have a table with 3 columns StartDate, EndDate, ElapsedTimeInSec.
I use an AFTER INSERT trigger to calculate the ElapsedTimeInSec.
I would like to do this:
If my start date is 2011-11-18 07:30:00 and my end date 2011-11-18 9:30:00 which give me a ElapsedtimeInSec of 7200 I would like to be able to split it this way.
Row 1 : 2011-11-18 07:30:00 / 2011-11-18 08:00:00 / 1800
Row 2 : 2011-11-18 08:00:00 / 2011-11-18 09:00:00 / 3600
Row 3 : 2011-11-18 09:00:00 / 2011-11-18 09:30:00 / 1800
How can I achieve this result ?
I dont think I made my explaination clear enough.
I have an actual table with data in it which as 2 field one with a StratDowntime and one with a EndDowntime and I would like to create a view of hours per hour base on a production shift of 12 hours (07:00:00 to 19:00:00) of the downtime.
So If I have a downtime from 2011-11-19 06:00:00 to 2011-11-19 08:00:00 I want in my report to see from 07:00:00 so the new rocrd should look like 2011-11-19 07:00:00 to 2011-11-19 08:00:00.
Another example if I do have downtime from 2011-11-19 10:30:00 to 2011-11-19 13:33:00 I should get in my report this
- 2011-11-19 10:30:00 to 2011-11-19 11:00:00
- 2011-11-19 11:00:00 to 2011-11-19 12:00:00
- 2011-11-19 12:00:00 to 2011-11-19 13:00:00
- 2011-11-19 13:00:00 to 2011-11-19 13:33:00
I hope this will clarify the question because none of the solution down there is actually doing this it is close but not on it.
thanks

You could try something like:
DECLARE #StartDate DATETIME = '11/18/2011 07:30:00',
#EndDate DATETIME = '11/18/2011 09:30:00',
#Runner DATETIME
IF DATEDIFF (mi, #StartDate, #EndDate) < 60
BEGIN
SELECT #StartDate,
#EndDate,
DATEDIFF (s, #StartDate, #EndDate)
RETURN
END
SET #Runner = CONVERT (VARCHAR (10), #StartDate, 101) + ' ' + CAST (DATEPART(hh, #StartDate) + 1 AS VARCHAR) + ':00:00'
WHILE #Runner <= #EndDate
BEGIN
SELECT #StartDate,
#Runner,
DATEDIFF (s, #StartDate, #Runner)
SET #StartDate = #Runner
SET #Runner = DATEADD(hh, 1, #Runner)
END
SET #Runner = CONVERT (VARCHAR (10), #EndDate, 101) + ' ' + CAST (DATEPART(hh, #EndDate) AS VARCHAR) + ':00:00'
SELECT #Runner,
#EndDate,
DATEDIFF (s, #Runner, #EndDate)

CTE:
DECLARE #beginDate DATETIME,
#endDate DATETIME
SELECT #beginDate = '2011-11-18 07:30:00',
#endDate = '2011-11-18 09:33:10'
DECLARE #mytable TABLE
(
StartDowntime DATETIME,
EndDowntime DATETIME,
ElapsedDowntimesec INT
)
-- Recursive CTE
;WITH Hours
(
BeginTime,
EndTime,
Seconds
)
AS
(
-- Base case
SELECT #beginDate,
DATEADD(MINUTE, ( DATEPART(MINUTE, #beginDate) * -1 ) + 60, #beginDate),
DATEDIFF
(
SECOND,
#beginDate,
CASE
WHEN #endDate < DATEADD(MINUTE, ( DATEPART(MINUTE, #beginDate) * -1 ) + 60, #beginDate) THEN #endDate
ELSE DATEADD(MINUTE, ( DATEPART(MINUTE, #beginDate) * -1 ) + 60, #beginDate)
END
)
UNION ALL
-- Recursive
SELECT Hours.EndTime,
CASE
WHEN #endDate < DATEADD(MINUTE, ( DATEPART(MINUTE, Hours.BeginTime) * -1 ) + 120, Hours.BeginTime) THEN #endDate
ELSE DATEADD(minute, ( DATEPART(MINUTE, Hours.BeginTime) * -1 ) + 120, Hours.BeginTime)
END,
DATEDIFF
(
SECOND,
Hours.EndTime,
CASE
WHEN #endDate < DATEADD(MINUTE, ( DATEPART(MINUTE, Hours.BeginTime) * -1 ) + 120, Hours.BeginTime) THEN #endDate
ELSE DATEADD(MINUTE, ( DATEPART(MINUTE, Hours.BeginTime) * -1 ) + 120, Hours.BeginTime)
END
)
FROM Hours
WHERE Hours.BeginTime < #endDate
)
INSERT INTO #myTable
SELECT *
FROM Hours
WHERE BeginTime < #endDate
SELECT * FROM #myTable
Results
BeginTime EndTime Seconds
2011-11-18 07:30:00.000 2011-11-18 08:00:00.000 1800
2011-11-18 08:00:00.000 2011-11-18 09:00:00.000 3600
2011-11-18 09:00:00.000 2011-11-18 09:33:10.000 1990

You can use a table valued function applied like SELECT * FROM [dbo].split('2011-11-02 12:55:00','2011-11-02 13:05:00')
Function defintion:
CREATE FUNCTION [dbo].[split] (#d1 DATETIME, #d2 DATETIME)
RETURNS #result TABLE (
StartDate DATETIME,
EndDate DATETIME,
ElapsedTimeSeconds INT
)
AS
BEGIN
-- Store intermediate values in #tmp, using ix as driver for start times.
DECLARE #tmp TABLE (ix INT NOT NULL IDENTITY(0,1) PRIMARY KEY
, d1 DATETIME, d2 DATETIME)
-- Insert first hole hour lower than start time
INSERT INTO #tmp (d1) SELECT DATEADD(HOUR, DATEDIFF(HOUR, -1, #d1), -1)
-- Calculate expected number of intervals
DECLARE #intervals INT = DATEDIFF(HOUR, #d1, #d2) - 1
-- insert all intervals
WHILE #intervals > 0
BEGIN
INSERT INTO #tmp (d1, d2) select top 1 d1, d2 FROM #tmp
SET #intervals = #intervals - 1
END
-- Set start and end time for all whole hour intervals
UPDATE #tmp SET d1 = DATEADD(hour, ix, d1)
, d2 = DATEADD(hour, ix + 1, d1)
-- Set correct start time for first interval
UPDATE #tmp SET d1 = #d1 WHERE d1 <= #d1
-- Insert end interval
INSERT INTO #tmp (d1, d2)
SELECT MAX(d2), #d2 FROM #tmp
-- Delete non-empty last interval
DELETE FROM #tmp WHERE d1 = d2
-- Insert #tmp to #result
INSERT INTO #result (StartDate, EndDate)
SELECT d1, d2 FROM #tmp
-- Set interval lengths
UPDATE #result SET ElapsedTimeSeconds = DATEDIFF(second, StartDate, EndDate)
return
END
GO
To get a result from an existing table, you can use CROSS APPLY. Assuming a table YourTable with StartTime and EndTime you can do something like
SELECT s.*, y.* FROM YourTable y
cross apply dbo.split(y.StartTime, y.EndTime) s
WHERE y.EndTime < '2011-09-11'
to get a result with a kind of join between input data and output table.

Related

PostgreSQL Time Dimension (By Hours and Days) Error

I am am building a Time Dimension table in PostgreSQL with DATE_ID and DATE_DESC.
My T-SQL (works perfectly) script is:
set DATEFIRST 1
;WITH DATES AS (
SELECT CAST('2019-01-01 00:00:00.000' AS datetime) AS [DATE]
UNION ALL
SELECT DATEADD(HH,1,[DATE])
FROM DATES
WHERE DATEADD(HH,1,[DATE]) <= CAST('2019-12-31' AS datetime)
)
SELECT
DATE_ID, DATE_DESC
from
(
SELECT
CONVERT(int, CONVERT(char(8), DATE, 112)) AS DATE_ID,
DATE AS DATE_DESC
FROM
DATES)a
order by 1
OPTION (MAXRECURSION 0)
At the moment Im trying to convert this code to PostgreSQL readable one and it does not work..
Here is mine at the moment:
set EXTRACT(DOW FROM TIMESTAMP '2019-01-01 00:00:00.000')+1
;WITH DATES AS (
SELECT CAST('2019-01-01 00:00:00.000' AS timestamp) AS DATE
UNION ALL
SELECT CURRENT_DATE + INTERVAL '1 hour'
FROM DATES
WHERE CURRENT_DATE + INTERVAL '1 hour' <= CAST('2019-12-31' AS timestamp)
)
SELECT DATE_ID, DATE_DESC from
(SELECT cast(to_char((DATE)::TIMESTAMP,'yyyymmddhhmiss') as BIGInt) AS DATE_ID,
DATE AS DATE_DESC
FROM
DATES)a
order by 1
OPTION (MAXRECURSION 0)
I need all the hours (24h) between 2019-01-01 and 2019-12-31 . At the moment I think OPTION (MAXRECURSION 0) and set EXTRACT(DOW FROM TIMESTAMP '2019-01-01 00:00:00.000')+1 is not working properly.
Its a problem of Recursive CTE, In Postgresql, your desired query will be like below
WITH recursive DATES AS (
SELECT CAST('2019-01-01 00:00:00.000' AS timestamp) AS date_
UNION ALL
SELECT date_ + INTERVAL '1 hour'
FROM DATES
WHERE date_ + INTERVAL '1 hour' <= CAST('2019-12-31' AS timestamp)
)
SELECT DATE_ID, DATE_DESC from
(SELECT cast(to_char((date_)::TIMESTAMP,'yyyymmddhhmiss') as BIGInt) AS DATE_ID,
date_ AS DATE_DESC
FROM
DATES)a
order by 1
DEMO

Calculating the business differences in sql in the form of day, hours and minutes - SQL Server

With the below function I getting the result as 00:09:10 however I want the result to be as 01:00:10.
So hours is considered as considered as 1 day.
Example if hours is 30 then it will be 03:03:00 and so on
fn_GetHolidayMinutes : Get holiday in minutes between two dates and country
CREATE FUNCTION [dbo].[fn_GetHolidayMinutes]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
RETURNS BIGINT
AS
BEGIN
DECLARE #OUTPUT BIGINT;
DECLARE #HolidayList TABLE (HolidaysDate DATE)
-- Create Table #HolidayList
-- (
-- HolidaysDate date
-- )
DECLARE #Date1 DATE, #Date2 DATE
DECLARE holiday_cursor CURSOR FOR
SELECT StartDate,EndDate
FROM Holidays
WHERE IsActive = 1
AND CountryId = #CountryId
AND ((StartDate BETWEEN #StartDate AND #EndDate) OR
(EndDate BETWEEN #StartDate AND #EndDate))
OPEN HOLIDAY_CURSOR
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
WHILE ##FETCH_STATUS = 0
BEGIN
--INSERT INTO #HolidayList
INSERT INTO #HolidayList
SELECT DATEADD(DAY, number, #Date1) [Date]
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY, number, #Date1) <= #Date2
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
END
CLOSE HOLIDAY_CURSOR;
DEALLOCATE HOLIDAY_CURSOR;
(SELECT #OUTPUT= COUNT(DISTINCT HolidaysDate)
FROM #HolidayList
WHERE HolidaysDate BETWEEN #StartDate AND #EndDate
AND DATEPART(dw, HolidaysDate) NOT IN (SELECT DISTINCT number
FROM master..spt_values
WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT WorkingDay
FROM WorkingDays
WHERE CountryId = #CountryId AND IsActive = 1)
))
---print #OUTPUT; --this will give in days
--get the output in minutes
RETURN #OUTPUT * (SELECT TOP 1 STUFF(WorkingHours, 2, 2, '')
FROM dbo.WorkingDays
WHERE CountryId = #CountryId) * 60;
END
fn_GetWorkingDayMinuts :
CREATE FUNCTION [dbo].[fn_GetWorkingDayMinuts]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
--RETURNS BIGINT
RETURNS VARCHAR(250)
AS
BEGIN
DECLARE #Temp BIGINT
SET #Temp = 0
DECLARE #FirstDay DATE
SET #FirstDay = CONVERT(DATE, #StartDate, 112)
DECLARE #LastDay DATE
SET #LastDay = CONVERT(DATE, #EndDate, 112)
DECLARE #StartTime TIME
SET #StartTime = CONVERT(TIME, #StartDate)
DECLARE #FinishTime TIME
SET #FinishTime = CONVERT(TIME, #EndDate)
DECLARE #WorkStart TIME
SET #WorkStart = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkStartTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #WorkFinish TIME
SET #WorkFinish = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkEndTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #DailyWorkTime BIGINT
SET #DailyWorkTime = DATEDIFF(MINUTE, #WorkStart, #WorkFinish)
IF (#StartTime<#WorkStart)
BEGIN
SET #StartTime = #WorkStart
END
IF (#FinishTime>#WorkFinish)
BEGIN
SET #FinishTime=#WorkFinish
END
IF (#FinishTime<#WorkStart)
BEGIN
SET #FinishTime=#WorkStart
END
IF (#StartTime>#WorkFinish)
BEGIN
SET #StartTime = #WorkFinish
END
DECLARE #CurrentDate DATE
SET #CurrentDate = #FirstDay
DECLARE #LastDate DATE
SET #LastDate = #LastDay
WHILE(#CurrentDate<=#LastDate)
BEGIN
--IF (DATEPART(dw, #CurrentDate)!=1 AND DATEPART(dw, #CurrentDate)!=7)
IF(DATEPART(dw, #CurrentDate) IN (SELECT distinct number FROM master..spt_values WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT
WorkingDay FROM WorkingDays where CountryId=#CountryId and IsActive=1)
))
BEGIN
IF (#CurrentDate!=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + #DailyWorkTime
END
--IF it starts at startdate and it finishes not this date find diff between work finish and start as minutes
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #StartTime, #WorkFinish)
END
ELSE IF (#CurrentDate!=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #WorkStart, #FinishTime)
END
--IF it starts and finishes in the same date
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = DATEDIFF(MINUTE, #StartTime, #FinishTime)
END
END
SET #CurrentDate = DATEADD(day, 1, #CurrentDate)
END
-- Return the result of the function
IF #Temp<0
BEGIN
SET #Temp=0
END
--RETURN #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0, DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--RETURN #Temp
DECLARE #theMinutes INT
DECLARE #Result VARCHAR(250)
SET #theMinutes = #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0,
DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--SET #Result= concat((#theMinutes / 540),':' , (#theMinutes % 540) /
60, ':', (#theMinutes % 60))
SET #Result= concat((#theMinutes / ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)),':' , (#theMinutes % ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)) / 60, ':', (#theMinutes % 60))
RETURN #Result
END
So where to modify to the result as
BUSINESS HOURS CREATE DATE & TIME FIRST APPLY (DATE & TIME) TAT TIME CALCULATION RESULT
08h00-17h00: 9hrs/day 12-FEB-19 14:20 13-FEB-19 14:30 00:02:40 + 00:06:30 = 00:09:10 01:00:10

Find the missing hour with Lag analytic function

I have to find the missing hour in my table , for frequency = 1 I have to find a record per hour, if it's not the case, I have to display the missing hour.
here's my code
declare #StartDate datetime declare #EndDate datetime declare #now datetime set #now = getdate() set #StartDate = dateadd(day,-30,#now) set #EndDate = dateadd(day,-2,#now) Select Flow.Id,Flow.ComponentId, Frequency.Name frequencyName, Flow.MeasurementDate as MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) LagValue, abs( DATEDIFF (hour, MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) ) ) DifferenceDate , (CASE WHEN DATEDIFF (hour, MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) ) > '1' THEN 'Yes' ELSE 'No' END) AS Gap into #tab1 FROM Data.dbo.Flow inner join Data.dbo.Component on flow.ComponentId = Component.Id inner join Data.dbo.Frequency on Flow.Frequency = Frequency.Id Where flow.LoaderCode='TOT' and Flow.Frequency='1' and ScheduledVolume IS NOT NULL and MeasurementDate between #StartDate and #EndDate --and DATEDIFF (hour, MeasurementDate, LAG(MeasurementDate) OVER (ORDER BY MeasurementDate) ) >1 Group By Frequency.Name, Flow.MeasurementDate, Flow.ComponentId select * from #tab1
--if i right understood then try this
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
DECLARE #now DATETIME
IF OBJECT_ID('Tempdb..#tab1') IS NOT NULL
BEGIN
DROP TABLE #tab1
END
SET #now = GETDATE()
SET #StartDate = GETDATE() - 30
SET #EndDate = GETDATE() - 2
SELECT Flow.Id ,
Flow.ComponentId ,
Frequency.Name AS frequencyName ,
CONVERT(DATE, Flow.MeasurementDate) AS [Measurement Date] ,
DATEPART(HOUR, Flow.MeasurementDate) AS [Measurement Hour] ,
COALESCE(LAG(DATEPART(HOUR, Flow.MeasurementDate)) OVER ( PARTITION BY CONVERT(DATE, MeasurementDate) ORDER BY DATEPART(HOUR,
MeasurementDate) ),
0) AS [Measurement Previous Hour]
INTO #tab1
FROM Data.dbo.Flow
INNER JOIN Data.dbo.Component ON Flow.ComponentId = Component.Id
INNER JOIN Data.dbo.Frequency ON Flow.Frequency = Frequency.Id
WHERE Flow.LoaderCode = 'TOT'
AND Flow.Frequency = '1'
AND ScheduledVolume IS NOT NULL
AND CONVERT(DATE, MeasurementDate) BETWEEN CONVERT(DATE, #StartDate)
AND CONVERT(DATE, #EndDate)
SELECT T.* ,
CASE WHEN ( T.[Measurement Hour] - T.[Measurement Previous Hour] ) > 1
THEN ( T.[Measurement Hour] - T.[Measurement Previous Hour] - 1 )
ELSE 0
END AS [Missing Hours]
FROM #tab1a AS T
WHERE ( T.[Measurement Hour] - T.[Measurement Previous Hour] ) > 1

tsql select query by time from and time to

I need to have a select query where the query is filtered by time format like this.
From: 7:00 AM
To: 8:00 AM
for example:
DECLARE #TimeFrom varchar(7)
DECLARE #TimeTo varchar(7)
DECLARE #StartDate varchar(10)
DECLARE #EndDate varchar(10)
SET #TimeFrom = '7:00 AM'
SET #TimeTo = '8:00 AM'
SET #StartDate = '05/07/2014'
SET #EndDate = '05/07/2014'
SELECT *
FROM [Call]
WHERE LTRIM(RIGHT(CONVERT(VARCHAR(20),StartTime,100),7)) BETWEEN #TimeFrom AND #TimeTo
and CONVERT(VARCHAR, StartTime, 101) = '05/07/2014'
AND SubDispositionID LIKE ('SA%')
ORDER BY StartTime ASC
The problem with this query is I am also getting data from 7:00 PM to 8:00 PM.
It is because you compare STRINGS so 7:00 PM is between 7:00 AM AND 8:00 AM
I think you should avoid 'AM\PM' and use 24h notation:
SET #TimeFrom = '07:00'
SET #TimeTo = '08:00'
....
WHERE CONVERT(VARCHAR(5),StartTime,108) BETWEEN #TimeFrom AND #TimeTo
Here is conversion to VARCHAR(5) to cut seconds from time string.
DECLARE #TimeFrom varchar(7)
DECLARE #TimeTo varchar(7)
DECLARE #StartDate varchar(10)
DECLARE #EndDate varchar(10)
SET #TimeFrom = '7:00 AM'
SET #TimeTo = '8:00 AM'
SET #StartDate = '05/07/2014'
SET #EndDate = '05/07/2014'
SELECT *
FROM [Call]
WHERE CONVERT(varchar, StartTime, 108) BETWEEN (select CONVERT(varchar(8), cast(#TimeFrom as datetime), 108))
AND (select convert(varchar(8), cast(#TimeTo as datetime), 108))
and CONVERT(VARCHAR, StartTime, 101) = '05/07/2014'
AND SubDispositionID LIKE ('SA%')
ORDER BY StartTime ASC

Combining multiple CTE in TSQL

I have two CTEs and I want to combine them together. I tried a lot but I got a syntax errors. First Part:
declare #TimeRanges as TABLE (SessionStart datetime, SessionEnd datetime);
with TimeRanges as (
select #Start as StartTime, #Start + #TimeRange as EndTime
union all
select StartTime + #TimeRange, EndTime + #TimeRange
from TimeRanges
where EndTime < #Finish )
Here is the second part:
;with cte as
(
select SessionStartTime as changetime,1 as CC from Calls
union all
select SessionCloseTime,-1 from Calls
)
select top 1 changetime,rt from
(
select * from cte
cross apply
(select SUM(cc) as rt from cte c where c.changetime<=cte.changetime) rt
) v
order by rt desc
What I want to do:
#Start datetime,
#Finish datetime,
#TimeRange time
AS
BEGIN
SET NOCOUNT ON;
declare #res int SET #res = 0
declare #TimeRanges as TABLE (SessionStart datetime, SessionEnd datetime);
with TimeRanges as
( select #Start as StartTime, #Start + #TimeRange as EndTime
union all
select StartTime + #TimeRange, EndTime + #TimeRange
from TimeRanges
where EndTime < #Finish ),
cte as
(
select SessionStart as changetime,1 as CC from TimeRanges
union all
select SessionEnd,-1 from TimeRanges
)
select top 1 changetime,rt from
(
select * from cte
cross apply
(select SUM(cc) as rt from cte c where c.changetime<=cte.changetime) rt
) v
order by rt desc
select StartTime, EndTime,cte.rt
from TimeRanges as TR left outer join
dbo.Test as Test on TR.StartTime <= Test.SessionStartTime
and Test.SessionCloseTime < TR.EndTime
where Test.ScenarioID = 24
group by TR.StartTime, TR.EndTime,cte.rt
END
First CTE, groups or splits times according to the #timerange between StartTime and EndTime. For Example, StartTime 11:00 EndTime 11:10 and TimeRange 05:00(5 min) then splits them into two parts: 11:00 - 11:05 and 11:05 - 11:10. Second CTE counts something for each these ranges. Not important in here. I tried to combine them but I get there errors:
Invalid column name 'SessionStart'
Invalid object name 'TimeRanges'
Because in the TimeRanges CTE, you've named the columns differently:
with TimeRanges as
( select #Start as StartTime, #Start + #TimeRange as EndTime --StartTime and EndTime
union all
select StartTime + #TimeRange, EndTime + #TimeRange
from TimeRanges
where EndTime < #Finish ),
cte as
(
select StartTime as changetime,1 as CC from TimeRanges --StartTime, not SessionStart
union all
select EndTime,-1 from TimeRanges --EndTime
)
select top 1 changetime,rt from
(
select * from cte
cross apply
(select SUM(cc) as rt from cte c where c.changetime<=cte.changetime) rt
) v
order by rt desc
But you then attempt to refer to the CTE again in your second query. You can't do that - each CTE applies to a single query.
You could repeat it:
with TimeRanges as
( select #Start as StartTime, #Start + #TimeRange as EndTime --StartTime and EndTime
union all
select StartTime + #TimeRange, EndTime + #TimeRange
from TimeRanges
where EndTime < #Finish )
select StartTime, EndTime,cte.rt
from TimeRanges as TR left outer join
dbo.Test as Test on TR.StartTime <= Test.SessionStartTime
and Test.SessionCloseTime < TR.EndTime
where Test.ScenarioID = 24
group by TR.StartTime, TR.EndTime,cte.rt