SQL Query by time interval - sql

So I have used this post as a reference, however I would like to count all the rows based on a 15 minute time period.
Here is what I have so far:
SELECT DateAdd(minute, DateDiff(minute, 0, [datetime]), 0) as Timestamp,
Count(*) as Tasks
FROM [table]
GROUP BY DateAdd(minute, DateDiff(minute, 0, [datetime]), 0)
ORDER BY Timestamp
This is great for getting rows per minute, however I need 15 minutes...
So I change:
DateAdd(minute, DateDiff(minute, 0, [datetime]), 0)
to
DateAdd(minute, DateDiff(minute, 0, [datetime]), 15)
however that is just pushing the date 15 days ahead.
Any help is appreciated!

To get 15 minutes, divide by 15 (and then multiply again):
SELECT DateAdd(minute, 15*(DateDiff(minute, 0, [datetime]) / 15), 0
) as Timestamp,
Count(*) as Tasks
FROM [table]
GROUP BY (DateDiff(minute, 0, [datetime]) / 15)
ORDER BY Timestamp;
SQL Server does integer division. If you want to be unambiguous about your intentions, use FLOOR().

SELECT ROUND(DATEDIFF(SECOND,{d '1970-01-01'},[datetime])/(15 * 60),0) as Timestamp,
Count(*) as Tasks
FROM [table]
GROUP BY ROUND(DATEDIFF(SECOND,{d '1970-01-01'},[datetime])/(15 * 60),0)
ORDER BY Timestamp

Here is an alternative in case integer division causes an issue for you. It casts the datetime as a float and then uses floor().
SELECT convert(varchar,cast(round(floor(cast([datetime] as float(53))*24*4)/(24*4),5) as smalldatetime),108) as Timestamp,
Count(*) as Tasks
FROM [table]
GROUP BY convert(varchar,cast(round(floor(cast([datetime] as float(53))*24*4)/(24*4),5) as smalldatetime),108)
ORDER BY Timestamp
I normally change the (24*4) to 96 (the number of 15 minute intervals in a day), but thought I'd leave it so people can see how to adapt it for other time periods.

Related

How can I select one row of data per hour?

I'm new at sql.
There is something that makes me confused, i got data per minute, but i only need a row of it per hour or per 2 hours. For example when i select data from the previous day, it shows me 1440 rows and i need to reduce them to less rows to make some charts.
Thanks in advance.
when i use this query:
select [Value],[Time] from [AbsoluteData] where [Sensor] = '5100' and [Time] >= dateadd(day,datediff(day,1,GETDATE()),0) AND[Time] < dateadd(day, datediff(day, 0, GETDATE()), 0)
i got:
You can select on row per hour by using row_number() like this:
select t.*
from (select t.*,
row_number() over (partition by cast(datetimecol as date), datepart(hour, datetimecol)
order by datetimecol
) as seqnum
from t
) t
where seqnum = 1;
I cannot read your image and you don't have a sample query or sample data, so this uses generic names.
If the data drops in every minute and you want just one within a given range (last hour or last day), just restrict the rows to the range and pick 1:
select top 1
[Value], [Time]
from [AbsoluteData]
where [Sensor] = '5100'
and cast(Time as date) = cast(dateadd(day, -1, getdate()) as date)
order by Time desc;
(last one yesterday)
or:
set rowcount 1;
select [Value], [Time]
from [AbsoluteData]
where [Sensor] = '5100'
and cast(Time as date) = cast(dateadd(day, -1, getdate()) as date)
order by Time desc;
set rowcount 0;

Difficulty in displaying large number of values on a Chart

I am trying to display some records from a database on a chart. The records saved within one minute is usually about 70 records. That number of records would look insane on a line chart, yet it would be more insane and unrealistic to expect users to keep requesting to view records per minute when their data interest is between a four hours interval.
I decided to to group the records by minute, there I got stuck in the query.
Below is my query sample:
SELECT DISNTINCT YEAR(recievedon), MONTH(recievedon), DAY(recievedon), HOUR(recievedon), referenceprice
FROM dbname
WHERE recievedon >= '2015-06-05 10:30' AND recievedon <= '2015-06-05 10:50'
ORDER BY recievedon
How do I group the records by minute either using GROUP BY or DISTINCT
Secondly, is there a better way to render a large dataset in a (line) chart instead of grouping the records?
If I were to guess that you were using MySQL, then you can do use to_seconds(). The following gives the average reference price for each minute, along with the date/time of the first price in the interval:
select min(recievedon), avg(referenceprice)
from dbname
where recievedon >= '2015-06-05 10:30' AND recievedon <= '2015-06-05 10:50'
group by floor(to_seconds(receivedon) / 60)
EDIT:
In SQL Server, you can do:
select min(receivedon), avg(referenceprice)
from dbname
where recievedon >= '2015-06-05 10:30' AND recievedon <= '2015-06-05 10:50'
group by datediff(minute, 0, receivedon);
If you want the beginning of the period rather than the earlier timestamp:
select dateadd(minute, 0, datediff(minute, 0, receivedon)) as timeperiod,
avg(referenceprice)
from dbname
where recievedon >= '2015-06-05 10:30' AND recievedon <= '2015-06-05 10:50'
group by dateadd(minute, 0, datediff(minute, 0, receivedon)) ;
Using simple group by DATEPART without the care of the overflow. The SELECT is just the same with Gordon's answer.
SELECT
MIN(ReceivedOn) AS Time,
-- Assuming you need average price
AVG(ReferencePrice) AS ReferencePrice
FROM
dbname
WHERE
ReceivedOn BETWEEN '2015-06-05 10:30' AND '2015-06-05 10:50'
GROUP BY
DATEPART(YEAR, ReceivedOn),
DATEPART(MONTH, ReceivedOn),
DATEPART(DAY, ReceivedOn),
DATEPART(HOUR, ReceivedOn),
DATEPART(MINUTE, ReceivedOn)

How to sum time datatype in sql server

I have query which gives sum of total talk time for an Agent all the years
SELECT
CONVERT(TIME, DATEADD(s, SUM(( DATEPART(hh, TalkTime) * 3600 ) + ( DATEPART(mi, TalkTime) * 60 ) + DATEPART(ss, TalkTime)), 0))
FROM [CRMIntegration].[dbo].[Five9CallLog]
where AGENT_NAME = 'XYZ'
which is giving me '00:37:01.0000000'
but when i sum up total talk time for this year till now using the below query
SELECT
CONVERT(TIME, DATEADD(s, SUM(( DATEPART(hh, TalkTime) * 3600 ) + ( DATEPART(mi, TalkTime) * 60 ) + DATEPART(ss, TalkTime)), 0))
FROM [CRMIntegration].[dbo].[Five9CallLog]
where AGENT_NAME = 'XYZ'
and DateOfcall between
DATEADD(yy, DATEDIFF(yy,0,getdate()), 0) and dateadd(day,datediff(day,1,GETDATE()),0)
result of the query is '23:34:38.0000000',but this should be always less than or equal to the first result
Is the function i am using for calculating total talk time is correct?
I suspect your first result is greater than 1 day, but that is being truncated by using TIME. Instead of adding seconds to 0 and converting to TIME, you could use DATEDIFF() to get total minutes:
SELECT DATEDIFF(MINUTE,0,TalkTime)
Ideally you'd have a start/end time to use instead of 0, because you'll run into an overflow if you need to get too precise and try starting from 0. If it's always relative to the start of the day, you can use:
SELECT DATEDIFF(SECOND,CAST(TalkTime AS DATE),TalkTime)
Likewise, you could simply remove the TIME conversion from what you already have.

Group by Time Interval

I need to Group my Table into 15 minutes Intervals. I can do that with:
select dateadd(minute, datediff(minute, 0, ts) / 15 * 15, 0), sum (goodpieces)
from StationCount
Group by dateadd(minute, datediff(minute, 0, ts) / 15 * 15, 0)
But to display the returned data in a chart i need to insert also the intervals which don't have any data and aren't currently appearing in my select statement. How do i insert these?
Create a table with every possible timestamp in 15 minute increments, and do a LEFT JOIN from it to your query above.
SELECT * FROM timestamps LEFT JOIN (SELECT dateadd......) ON timestamps.timestamp = StationCount.ts
If you know your chart always covers a 24 hour period, you only need to create a table with the numbers 0-95, then for each entry add it to the start time of your chart.
SELECT *
FROM (SELECT dateadd(minute, <starttime>, number*15) timestamp FROM numbers) timestamps LEFT JOIN
(SELECT dateadd......) ON timestamps.timestamp = StationCount.ts
Something like this might help you.
declare #startDate datetime
,#endDate datetime
set #startDate = '2011-10-25'
set #endDate = '2011-10-26'
;with fifteenMinutes
as
(
select dateadd(minute, datediff(minute, 0, #startDate) / 15 * 15, 0) as q
UNION ALL
select dateadd(minute, 15, q)
from fifteenMinutes
where q < #endDate
)
select * from fifteenMinutes

Date Calculation Between two dates

I need some help doing a date calculation.
I have something that Expires every X number of days away from its Create Date
So, if the Create Date was 4/22 and the Expiration days were set to 10 it would expire
5/2, 5/12, 5/22, 6/1 etc...
I need to be able to tell people when their item is going to expire within 5 days
So for 5/2, I need to add this item to a count if the current date is between 4/27 and 5/2.
This is in SQL.
All we have are the RunDate, the CreateDate and the ExpirationDays
I've done the math calc to roughly get the Expiration date, but if it gets a remainder it's not helpful, and I don't want to skew anyone's answer by posting what I think it should be. I've tried quite a few ways and am getting a little desperate.
Any help would be greatly appreciated
EDIT:
I did the math for this and it looks like this
CreateDate + (((RunDate - CreateDate)/ExpireDays)*ExpireDays)) Between Rundate-1 and Rundate +5
But this gives me arithmetic overflow in SQL, so I'm not sure what to do...
In MySql you could do something
(ExpirationDays - (DATEDIFF(NOW(), CreateDate) % ExpirationDays)) > 5;
EDIT
For SQL Server you would do it a little different:
#expiringDays - (DATEDIFF(dd, ml.CreateDate, #date) % #expiringDays) > 5;
With Expirations As
(
Select Cast('2011-04-22' As datetime) As CreateDate, 10 As ExpirationDays
Union All
Select DateAdd( d, ExpirationDays, CreateDate ), ExpirationDays
From Expirations
Where CreateDate <= DateAdd(d,10,CURRENT_TIMESTAMP) --(arbitary end date)
)
Select *
From Expirations
Where CreateDate >= CURRENT_TIMESTAMP
And CreateDate <= DateAdd(d,5,CURRENT_TIMESTAMP)
Using similar logic to the math you used in your updated post:
With Expirations As
(
Select Cast('2011-04-22' As datetime) As CreateDate, 10 As ExpirationDays
Union All
Select DateAdd( d, ExpirationDays, CreateDate ), ExpirationDays
From Expirations
Where CreateDate <= DateAdd(d,10,CURRENT_TIMESTAMP) --(arbitary end date)
)
Select *
From Expirations
Where CreateDate >= DateAdd(d, -1, CURRENT_TIMESTAMP)
And CreateDate <= DateAdd(d, 5, CURRENT_TIMESTAMP)