select data for every 5 minute interval - sql-server

I have the following query which is giving me 24 hour interval data, I want to get the data for every 5 minute interval
IF OBJECT_ID('tempdb..#mytemptable') IS NOT NULL DROP TABLE #mytemptable;
SELECT AVG( CAST ([PT_100SCALED_VAL0] AS bigint) ) AS PT_100SCALED_VAL0_AVERAGE
INTO #MYTEMPTABLE FROM ( SELECT t1.[timestamp], t1.[PT_100SCALED_VAL0] FROM
[REPORT] t1 WHERE t1.[timestamp] >= '2016-01-06 00:00:00' and t1.[timestamp] <='2016-01-06 23:59:59' )
TEMPTABLE
SELECT t1.[timestamp], t1.[PT_100SCALED_VAL0] , RM_temp.* FROM [REPORT]
t1 , #MYTEMPTABLE RM_temp WHERE t1.[timestamp] >= '2016-01-06 00:00:00' and t1.[timestamp] <='2016-01-06 23:59:59' -- This select will give the final result.
my result for the above query is
timestamp PT_100SCALED_VAL0 PT_100SCALED_VAL0_AVERAGE
2016-01-06 13:31:27.807 1 5
2016-01-06 13:32:27.810 2 5
2016-01-06 13:33:27.817 3 5
2016-01-06 13:34:27.827 4 5
2016-01-06 13:35:27.827 5 5
2016-01-06 13:36:27.837 6 5
2016-01-06 13:37:27.840 7 5
2016-01-06 13:38:27.847 8 5
2016-01-06 13:39:27.850 9 5
my expected result is
timestamp PT_100SCALED_VAL0 PT_100SCALED_VAL0_AVERAGE
2016-01-06 13:35:27.827 5 5
2016-01-06 13:39:27.850 9 5
I have tried using with and partion by but i am getting error incorrect syntax near if

Declare #start datetime, #end datetime
Select #start=CAST(CAST(getdate() as date) as datetime), #end=CAST((DATEADD(DAY,1,#start)) as datetime)
;With DateTimeSequence( Dt ) as
(
Select #start as Stime
union all
Select DATEADD(MINUTE,5,Dt)
from DateTimeSequence
where Dt < DATEADD(MINUTE,-5,#end)
)select Dt as StartTime,DATEADD(MINUTE,5,Dt) as EndTime from DateTimeSequence
Option (MaxRecursion 1000)
Use the above CTE with your query and join with your query and use as desired.

Related

T-SQL - 3 month moving sum - preceding null values

Using SQL Server 2016. I have the following data table (sample)
Target Date Total
-----------------
2018-01-24 1
2018-02-28 1
2018-03-02 1
2018-03-08 1
2018-03-15 1
2018-03-30 1
2018-04-16 1
2018-04-18 1
2018-04-30 1
I would like to get to get a 3 month moving sum (grouping is by month):
Target Date Total_Sum
-----------------------
2018-01-01 1
2018-02-01 2
2018-03-01 6
2018-04-01 8
Ok, this should get the answer you want. Firstly you need to total the value your months, then you can do a running total for the last 3 months:
CREATE TABLE SampleTable (TargetDate date, Total int);
GO
INSERT INTO SampleTable
VALUES ('20180124', 1),
('20180228', 1),
('20180302', 1),
('20180308', 1),
('20180315', 1),
('20180330', 1),
('20180416', 1),
('20180418', 1),
('20180430', 1);
GO
SELECT *
FROM SampleTable;
GO
WITH Months AS (
SELECT DATEADD(MONTH,DATEDIFF(MONTH, 0, TargetDate),0) AS TargetMonth, SUM(Total) AS MonthTotal
FROM SampleTable
GROUP BY DATEADD(MONTH,DATEDIFF(MONTH, 0, TargetDate),0))
SELECT TargetMonth,
SUM(MonthTotal) OVER (ORDER BY TargetMonth ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS Last3Months
FROM Months;
GO
DROP TABLE SampleTable;
GO
Pls try the below code
;WITH CTE(TargetDate,Total)
AS
(
SELECT '2018-01-24', 1 UNION ALL
SELECT '2018-02-28', 1 UNION ALL
SELECT '2018-03-02', 1 UNION ALL
SELECT '2018-03-08', 1 UNION ALL
SELECT '2018-03-15', 1 UNION ALL
SELECT '2018-03-30', 1 UNION ALL
SELECT '2018-04-16', 1 UNION ALL
SELECT '2018-04-18', 1 UNION ALL
SELECT '2018-04-30', 1
)
SELECT STUFF(TargetDate,9,2,'01') AS TargetDate
,Total_Sum
FROM
(
SELECT TargetDate,Total_Sum
,ROW_NUMBER()OVER(PARTITION BY Total_Sum ORDER BY TargetDate) AS Seq
FROM
(
SELECT TargetDate
,SUM(Total )OVER(ORDER BY MONTH(TargetDate) ) AS Total_Sum
FROM CTE
)dt
)fnl
WHERE Seq=1
Result
TargetDate Total_Sum
---------------------
2018-01-01 1
2018-02-01 2
2018-03-01 6
2018-04-01 9

Select part of duration that occurs in specific hour of day

In SQL Server, I have a table of processes with a starttime and an endtime, from which I can calculate a duration using DATEDIFF.
Name StartTime EndTime
------------------------------------------------
process1 2016-10-10 11:10 2016-10-10 11:20
process2 2016-10-10 11:40 2016-10-10 12:30
How can I select the timespan of the process duration that occured in specific hours of the day (11 and 12) in seconds?
So process1 would be 10 minutes in hour 11.
process2 would be 20 minutes in hour 11, 30 minutes in hour 12.
Here's a sample that will generate hourly records for each source record. It uses a recursive CTE to move from the StartTime of each record through the EndTime. It may need some slight modifications to make it work in your case, but hopefully you can get the idea of how this method works.
Note that, as shown in the sample below, this will work properly even if the time span crosses a date boundary.
--==================================================================================
-- Do some quick setup to get a temporary table populated with data to use:
--==================================================================================
IF OBJECT_ID('tempdb..#ProcessHistory', 'U') IS NOT NULL DROP TABLE #ProcessHistory;
CREATE TABLE #ProcessHistory (
Name VARCHAR(20),
StartTime DATETIME,
EndTime DATETIME
)
INSERT INTO #ProcessHistory
VALUES ('process1', '2016-10-10 11:10', '2016-10-10 11:20'),
('process2', '2016-10-10 11:40', '2016-10-10 12:30'),
('process3', '2016-10-10 22:21', '2016-10-11 02:36');
--==================================================================================
-- Use a recursive CTE to generate hourly data for each record:
--==================================================================================
WITH HourlyData AS (
-- Anchor:
SELECT
ph.Name [ProcessName],
ph.StartTime [StartTime],
ph.EndTime [EndTime],
-- Get the current hour with date:
DATEADD(MINUTE, -DATEPART(MINUTE, ph.StartTime), ph.StartTime) [CurrentHour],
-- Calculate the next hour for use later:
DATEADD(MINUTE, 60 - DATEPART(MINUTE, ph.StartTime), ph.StartTime) [NextHour],
-- Determine how many minutes the process was active this hour:
CASE
WHEN DATEDIFF(MINUTE, ph.StartTime, ph.EndTime) > 60 - DATEPART(MINUTE, ph.StartTime)
THEN 60 - DATEPART(MINUTE, ph.StartTime)
ELSE DATEDIFF(MINUTE, ph.StartTime, ph.EndTime)
END [Minutes]
FROM #ProcessHistory ph
UNION ALL
-- Recurse:
SELECT
hd.ProcessName,
hd.StartTime,
hd.EndTime,
hd.NextHour [CurrentHour],
DATEADD(HOUR, 1, hd.NextHour) [NextHour],
-- Determine how many minutes the process was active this hour:
CASE
WHEN DATEDIFF(MINUTE, hd.NextHour, hd.EndTime) < 60
THEN DATEDIFF(MINUTE, hd.NextHour, hd.EndTime)
ELSE 60
END
FROM HourlyData hd
WHERE hd.NextHour < hd.EndTime
)
SELECT
hd.ProcessName,
hd.CurrentHour [HourWithDate],
CONVERT(DATE, hd.CurrentHour) [Date],
DATEPART(HOUR, hd.CurrentHour) [Hour],
hd.Minutes
FROM HourlyData hd
ORDER BY
hd.ProcessName,
hd.CurrentHour;
The output from the above sample would look like this:
ProcessName HourWithDate Date Hour Minutes
process1 2016-10-10 11:00:00.000 2016-10-10 11 10
process2 2016-10-10 11:00:00.000 2016-10-10 11 20
process2 2016-10-10 12:00:00.000 2016-10-10 12 30
process3 2016-10-10 22:00:00.000 2016-10-10 22 39
process3 2016-10-10 23:00:00.000 2016-10-10 23 60
process3 2016-10-11 00:00:00.000 2016-10-11 0 60
process3 2016-10-11 01:00:00.000 2016-10-11 1 60
process3 2016-10-11 02:00:00.000 2016-10-11 2 36
To handle general cases, you could try something like
--drop table #processes
CREATE TABLE #processes
(
name varchar(50),
StartTime Datetime,
EndTime DateTime
);
insert #processes VALUES('proc1','20161010 11:10','20161010 11:20');
insert #processes VALUES('proc2','20161010 11:40','20161010 12:20');
insert #processes VALUES('proc3','20161010 10:40','20161010 12:20');
;WITH HRS AS (SELECT 0 HR
UNION ALL
SELECT HR + 1 FROM HRS WHERE HR < 23),
MINS AS (SELECT 0 MN
UNION ALL
SELECT MN + 1 FROM MINS WHERE MN < 59),
TIMES AS (SELECT HR,MN FROM HRS CROSS JOIN MINS)
SELECT name,starttime,endtime,Count(0) AS mins FROM #processes
JOIN TIMES
ON (HR > datepart(hh,Starttime)
OR HR = datepart(hh,Starttime) AND MN >= datepart(n,STARTtIME))
AND
(HR < datepart(hh, EndTime)
OR HR = datepart(hh, EndTime) AND MN < datepart(n,EndTime))
WHERE HR = 11 --hour is 11
GROUP BY name,
starttime,
endtime
drop table #processes;
create table #temp (Name varchar(5), starttime datetime, EndTime datetime)
insert into #temp values(1,'2016-10-10 11:10','2016-10-10 11:20' )
insert into #temp values(2,'2016-10-10 11:40','2016-10-10 12:30' )
insert into #temp values(2,'2016-10-10 10:40','2016-10-10 11:30' )
insert into #temp values(2,'2016-10-10 10:40','2016-10-10 12:30' )
DECLARE #firstTime time ,#secondTime time
set #firstTime ='11:00'
set #secondTime ='12:00'
select
CASE WHEN CONVERT(time(0), starttime) < #firstTime AND CONVERT(time(0), EndTime) > #secondTime THEN DATEDIFF(ss,#firstTime,#secondTime)
WHEN CONVERT(time(0), EndTime) > #secondTime THEN DATEDIFF(ss,CONVERT(time(0), starttime),#secondTime)
WHEN CONVERT(time(0), starttime) < #firstTime THEN DATEDIFF(ss,CONVERT(time(0), EndTime),#secondTime)
ELSE DATEDIFF(ss,starttime,EndTime)
END
from #temp
SELECT CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,'2016-10-10 11:10','2016-10-10 12:20'),'2011-01-01 00:00:00.000') AS TIME)
as timeDifference
With timeDifference -
SELECT CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,StartTime,EndTime),'2011-01-01 00:00:00.000') AS TIME)
as timeDifference
from #YourTableName
With Days and TimeDiffernece
declare #start_time as varchar(150);
declare #end_time as varchar(150);
set #start_time='2016-10-10 10:10';
set #end_time='2016-10-12 12:10'
SELECT datediff(day,#start_time,#end_time) as dayDifference,
CAST(DATEADD(MINUTE,DATEDIFF(MINUTE,#start_time,#end_time),'2011-01-01 00:00:00') AS TIME(0))
as timeDifference
I think this does the trick, but it's pretty ugly. Maybe someone can do it more elegantly?
SELECT
case
when HOUR(starttime) < 11 AND HOUR(endtime) = 11 then minute(endtime)
when HOUR(starttime) < 11 AND HOUR(endtime) > 11 then 60
when HOUR(starttime) = 11 AND HOUR(endtime) = 11 then minute(endtime) - minute(starttime)
when HOUR(starttime) = 11 AND HOUR(endtime) > 11 then 60 - minute(starttime)
else 0
end AS ProcessTimeHour_11,
case
when HOUR(starttime) < 12 AND HOUR(endtime) = 12 then minute(endtime)
when HOUR(starttime) < 12 AND HOUR(endtime) > 12 then 60
when HOUR(starttime) = 12 AND HOUR(endtime) = 12 then minute(endtime) - minute(starttime)
when HOUR(starttime) = 12 AND HOUR(endtime) > 12 then 60 - minute(starttime)
else 0
end AS ProcessTimeHour_12
from StuffAndThings

sql query to get running Average,Minimum,Maximum,Total,standard deviation, count for every 5 minutes

I have a table with time (column) and power (column). I want to calculate different result sets on following table data:
My Table:
[timestamp] [power]
2016-01-06 13:32:27 1
2016-01-06 13:33:27 2
2016-01-06 13:34:27 3
2016-01-06 13:35:27 4
2016-01-06 13:36:27 5
2016-01-06 13:37:27 6
2016-01-06 13:38:27 7
2016-01-06 13:39:27 8
2016-01-06 13:40:27 9
2016-01-06 13:41:27 10
Total as:
[timestamp] [power] Total
2016-01-06 13:32:27 1 1
2016-01-06 13:33:27 2 3
2016-01-06 13:34:27 3 6
2016-01-06 13:35:27 4 10
2016-01-06 13:36:27 5 15
2016-01-06 13:37:27 6 21
2016-01-06 13:38:27 7 28
2016-01-06 13:39:27 8 36
2016-01-06 13:40:27 9 45
2016-01-06 13:41:27 10 55
Total for every 5 minute as:
[timestamp] [power] Total_every_5minutes
--2016-01-06 13:32:27 1 1
--2016-01-06 13:33:27 2 3
--2016-01-06 13:34:27 3 6
--2016-01-06 13:35:27 4 10
2016-01-06 13:36:27 5 15
--2016-01-06 13:37:27 6 21
--2016-01-06 13:38:27 7 28
--2016-01-06 13:39:27 8 36
2016-01-06 13:40:27 9 45
Similarly I want to calculate for average, minimum, maximum, standard deviation, & count. As of now I have written a query which will add a column with,
Please note:
That I should not write stored procedure. As I have a windows application where user selects database and it will list the tables, from the listed tables user selects the columns and on a particular column he will set to calculate total or etc.. Upon selection the query is building. and the query will execute and bind the results to datagridview.
IF OBJECT_ID('tempdb..#mytemptable') IS NOT NULL DROP TABLE #mytemptable;
SELECT SUM( CAST ([power] AS bigint) ) AS power_TOTAL INTO #MYTEMPTABLE
FROM ( SELECT t1.[timestamp], t1.[power] FROM [REPORT] t1 ) TEMPTABLE
SELECT t1.[timestamp], t1.[power], RM_temp.* FROM [REPORT] t1 , #MYTEMPTABLE RM_temp;
may be this will work for you based on your data
DECLARE #Table1 TABLE
( timestamp varchar(19), power int)
;
INSERT INTO #Table1
( timestamp , power )
VALUES
('2016-01-06 13:32:27', 1),
('2016-01-06 13:33:27', 2),
('2016-01-06 13:34:27', 3),
('2016-01-06 13:35:27', 4),
('2016-01-06 13:36:27', 5),
('2016-01-06 13:37:27', 6),
('2016-01-06 13:38:27', 7),
('2016-01-06 13:39:27', 8),
('2016-01-06 13:40:27', 9),
('2016-01-06 13:41:27', 10)
;
Select [timestamp],[power] from (
SELECT timestamp, power , RunningTotal = power + COALESCE(
(
SELECT SUM(power)
FROM #Table1 AS i
WHERE i.timestamp < o.timestamp), 0
)
FROM #Table1 AS o)TT where exists (Select * from (select power * 5 ID from #Table1) T WHERE T.id = TT.RunningTotal )
ORDER BY timestamp;

SQL Server Order by numeric varchar

I have this query:
select cast(MONTH(c.dataregistro) as VARCHAR(2)) as DATA, numberofquotesreturned, count(*) AS CountNumberQuotes from contratacao c
inner join teleportpedidocotacao tpc on c .idcontratacao = tpc.idcontratacao
where cast(c.dataregistro as date) > '2014-01-01 00:00:00' AND numberofquotesreturned = 5
group by numberofquotesreturned, cast(MONTH(c.dataregistro) as VARCHAR(2))
order by cast(MONTH(c.dataregistro) as VARCHAR(2))
The results are:
10 5 347
2 5 112
3 5 914
4 5 786
5 5 1184
6 5 2361
7 5 2430
8 5 2184
9 5 2709
I want to order by the whole number on the first column and as you can see the '10' comes first. How can I fix it?
Just remove the cast to varchar:
select MONTH(c.dataregistro) as DATA, numberofquotesreturned, count(*) AS CountNumberQuotes from contratacao c
inner join teleportpedidocotacao tpc on c .idcontratacao = tpc.idcontratacao
where cast(c.dataregistro as date) > '2014-01-01 00:00:00' AND numberofquotesreturned = 5
group by numberofquotesreturned, MONTH(c.dataregistro)
order by MONTH(c.dataregistro)

How can I calculate time duration between two rows of a column in SQL Server?

I have a data like this in the database
ID Server DownTime ServerStatus
--- ----------------------- ------------
1 2012-03-30 00:00:00.000 1
2 2012-03-30 00:30:00.000 0
3 2012-03-30 01:00:00.000 0
4 2012-03-30 01:30:00.000 0
5 2012-03-30 02:00:00.000 1
6 2012-03-30 02:30:00.000 1
7 2012-03-30 03:00:00.000 0
8 2012-03-30 03:30:00.000 1
I need a query or stored procedure that will give me output as
Start Time EndTime TotalDownTimeinMinutes
------------ ------------ ----------------------
3/30/12 0:30 3/30/12 2:00 90
3/30/12 3:00 3/30/12 3:30 30
-- because each "back up" can relate to multiple "down" times,
-- we take the longest period using MIN
SELECT Min(ServerDownTime) StartTime,
UpTime EndTime,
DateDiff(MI, Min(ServerDownTime), UpTime)
FROM
(
SELECT Down.ServerDownTime,
(-- subquery gives you the time when it came back up
SELECT Top 1 Up.ServerDownTime
FROM Tbl Up
WHERE Up.ServerDownTime > Down.ServerDownTime
AND Up.ServerStatus=1
ORDER BY Up.ServerDownTime ASC) UpTime
FROM Tbl Down
WHERE Down.ServerStatus=0 -- find all the downs
) X
GROUP BY UpTime
ORDER BY UpTime
You can test the above query using this DDL
create table Tbl
(
ID int,
ServerDownTime datetime,
ServerStatus bit
)
insert Tbl select
1 ,'2012-03-30 00:00:00.000', 1 union all select
2 ,'2012-03-30 00:30:00.000', 0 union all select
3 ,'2012-03-30 01:00:00.000', 0 union all select
4 ,'2012-03-30 01:30:00.000', 0 union all select
5 ,'2012-03-30 02:00:00.000', 1 union all select
6 ,'2012-03-30 02:30:00.000', 1 union all select
7 ,'2012-03-30 03:00:00.000', 0 union all select
8 ,'2012-03-30 03:30:00.000', 1
Or if you're on the web and nowhere near a SQL Server, here's an SQL Fiddle
This solution is based on recursive CTE's:
DECLARE #MyTable TABLE (
ID INT PRIMARY KEY,
ServerDownTime DATETIME NOT NULL,
UNIQUE (ServerDownTime),
ServerStatus BIT NOT NULL
);
INSERT #MyTable (ID, ServerDownTime, ServerStatus)
SELECT 1,'2012-03-30T00:00:00',1 UNION ALL
SELECT 2,'2012-03-30T00:30:00',0 UNION ALL
SELECT 3,'2012-03-30T01:00:00',0 UNION ALL
SELECT 4,'2012-03-30T01:30:00',0 UNION ALL
SELECT 5,'2012-03-30T02:00:00',1 UNION ALL
SELECT 6,'2012-03-30T02:30:00',1 UNION ALL
SELECT 7,'2012-03-30T03:00:00',0 UNION ALL
SELECT 8,'2012-03-30T03:30:00',1;
WITH Base
AS
(
SELECT *, ROW_NUMBER() OVER(ORDER BY t.ServerDownTime) AS RowNum
FROM #MyTable t
), DownTimeGrouping
AS
(
SELECT crt.RowNum,
crt.ID,
crt.ServerDownTime,
crt.ServerStatus,
CASE WHEN crt.ServerStatus=0 THEN 1 END AS GroupID,
CASE WHEN crt.ServerStatus=0 THEN 1 ELSE 0 END AS LastGroupID
FROM Base crt
WHERE crt.RowNum=1
UNION ALL
SELECT crt.RowNum,
crt.ID,
crt.ServerDownTime,
crt.ServerStatus,
CASE
WHEN prev.ServerStatus=0 AND crt.ServerStatus IN(0,1) THEN prev.GroupID
WHEN prev.ServerStatus=1 AND crt.ServerStatus=0 THEN prev.LastGroupID+1
END AS GroupID,
CASE
WHEN prev.ServerStatus=0 AND crt.ServerStatus IN(0,1) THEN prev.GroupID
WHEN prev.ServerStatus=1 AND crt.ServerStatus=0 THEN prev.LastGroupID+1
WHEN prev.ServerStatus=1 AND crt.ServerStatus=1 THEN prev.GroupID
END AS LastGroupID
FROM Base crt
INNER JOIN DownTimeGrouping prev ON crt.RowNum=prev.RowNum+1
)
SELECT *, DATEDIFF(MINUTE,x.StartTime,x.EndTime) AS MinutesDiff
FROM (
SELECT t.GroupID, MIN(t.ServerDownTime) AS StartTime, MAX(t.ServerDownTime) AS EndTime
FROM DownTimeGrouping t
WHERE t.GroupID IS NOT NULL
GROUP BY t.GroupID
) x
The basic idea is to group the rows starting with a ServerStatus=0 row and ending with a ServerStatus=1 row. For example, if you run this query you will see the downtime groups (column GroupID)::
WITH Base
AS
(...), DownTimeGrouping
AS
(...)
SELECT *
FROM DownTimeGrouping g
ORDER BY g.RowNum
RowNum ID ServerDownTime ServerStatus GroupID LastGroupID
-------------------- ----------- ----------------------- ------------ ----------- -----------
1 1 2012-03-30 00:00:00.000 1 NULL 0
2 2 2012-03-30 00:30:00.000 0 1 1
3 3 2012-03-30 01:00:00.000 0 1 1
4 4 2012-03-30 01:30:00.000 0 1 1
5 5 2012-03-30 02:00:00.000 1 1 1
6 6 2012-03-30 02:30:00.000 1 NULL 1
7 7 2012-03-30 03:00:00.000 0 2 2
8 8 2012-03-30 03:30:00.000 1 2 2

Resources