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)
Related
I have a small question about SQL Server: how to get the last 30 days information from this column from table1:
created_at
updated_at
2020-02-05T01:25:42Z
2020-02-05T01:25:42Z
2020-05-05T02:31:56Z
2020-05-05T02:31:56Z
With the above data, I would need something like day count within 30 days.
I have tried
SELECT * FROM table1
DATEDIFF(CAST(SUBSTR(updated_at,1,10)) AS VARCHAR,CURRENT_TIMESTAMP) BETWEEN 0 AND 30 ;
and
SELECT * FROM table1
WHERE updated_at BETWEEN DATETIME('now', '-30 days') AND DATETIME('now', 'localtime')
Would need your expertise to help me with this query
Thank you!
SELECT *
FROM (
SELECT otherColumns
, DATEADD(mi, DATEDIFF(mi, GETUTCDATE(), GETDATE()), updated_at) AS updated_at
FROM table1
) b
WHERE CAST(b.updated_at AS DATE) >= DATEADD(DAY,-30,GETDATE())
I think this will help you
If you want a count of updates by day for 30 (or so) days, then:
SELECT CONVERT(DATE, updated_at) as dte, COUNT(*)
FROM table1
WHERE updated_at >= DATEADD(DAY, -30, CONVERT(DATE, GETDATE()))
GROUP BY CONVERT(DATE, updated_at)
ORDER BY CONVERT(DATE, updated_at);
Note that SQLite date/time functions (which your code uses) are very peculiar to to SQLite. So are SQL Server's -- although I personally find them easier to remember.
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.
am working with MS SQL express and Ignition SCADA by http://www.inductiveautomation.com/
In the SCADA package you are able to create tags from SQL query's. I am trying to use SQL tags to calculate the average packages per minute in a 30min time frame. I was able to do this with two tags and an expression
SELECT MAX(L8Total)
FROM Slicing_tot
WHERE t_stamp BETWEEN DATEADD(minute, -30, GETDATE()) AND GETDATE()
SELECT MIN(L8Total)
FROM Slicing_tot
WHERE t_stamp BETWEEN DATEADD(minute, -30, GETDATE()) AND GETDATE()
What I would like to do from here is store the expressions value and find the max and average for the last 30 days based on time. But I have no idea how to filter 30days of information at a certain time
IE what was the max packages per minute we had at 10:30 from the last 30 days
IE what was the average packages per minute we had at 11:45 form the last 30 days
Please keep in mind that I am new to SQL
SELECT DATEPART(MINUTE, t_stamp)
,MAX(L8Total)
,MIN(L8Total)
FROM Slicing_tot
WHERE ( CONVERT(DATE, t_stamp) >= CONVERT(DATE, GETDATE() - 30)
AND CONVERT(DATE, t_stamp) <= CONVERT(DATE, GETDATE())
)
AND ( CONVERT(TIME, #variable) >= '22:30'
AND CONVERT(TIME, #variable) <= '23:00'
)
GROUP BY DATEPART(MINUTE, t_stamp)
GETDATE()-30 will get you datetime of today minus 30 days ago. Since you are working with datetime field it is best to convert it to date to make sure that you get correct date range. Use of >= and <= is better than between because you is always clear what you doing. Read #Aaron's blog
than for the second part just convert your datetime column to time to limit to specific range during the day.
The following would select between 10 & 11 AM over those 30 days
SELECT MIN(L8Total)
FROM Slicing_tot
WHERE t_stamp BETWEEN DATEADD(dd, -30, GETDATE()) AND GETDATE()
and Datepart(hh,t_stamp) between 10 and 11
or you could compare the time part of the t_stamp to time
SELECT MIN(L8Total)
FROM Slicing_tot
WHERE t_stamp BETWEEN DATEADD(dd, -30, GETDATE()) AND GETDATE()
and convert(time, t_stamp) between '10:30:00.000' and '10:31:00.000'
which would give you the results between 10:30 and 10:31 inclusive of the end points over the last 30 days.
I want to write a select that aggregates over data (which has a DATETIME column as ID) with ANY interval theoretically possible (like 1hr, 1hr and 22seconds, 1year and 3minutes, etc. ).
This select should be able to aggregate by 1hr, 12min, 14seconds and should return 3 rows
SELECT DATEPART(YEAR,id) as year,
DATEPART(MONTH,id) as month,
DATEPART(DAY,id) as day,
DATEPART(HOUR,id) as hour,
DATEPART(MINUTE,id) as minute,
AVG([Open]),
AVG([Close]),
AVG([Min]),
AVG([Max])
FROM QuoteHistory
where id between '2000-02-06 17:00:00.000' and '2000-02-06 20:36:42.000'
GROUP BY
DATEPART(YEAR,id),
DATEPART(MONTH,id),
DATEPART(DAY,id),
DATEPART(HOUR,id),
DATEPART(MINUTE,id)
ORDER BY 1,2,3,4,5;
I am kind of stuck here and can't get my head around this problem.. For "simple intervals" like "30 minutes" i could just add a modulo
DATEPART(MINUTE,id)%2
but when the interval "touches" more than 1 part of the date, I'm stuck.
Any help appreciated, thx!
Assuming some parameters here:
;WITH Date_Ranges AS (
SELECT
#min_datetime AS start_datetime,
DATEADD(SECOND, #seconds,
DATEADD(MINUTE, #minutes,
DATEADD(HOUR, #hours,
DATEADD(DAY, #days,
DATEADD(WEEK, #weeks,
DATEADD(MONTH, #months,
DATEADD(YEAR, #years, #min_datetime))))))) AS end_datetime
UNION ALL
SELECT
DATEADD(SECOND, 1, end_datetime),
DATEADD(SECOND, #seconds,
DATEADD(MINUTE, #minutes,
DATEADD(HOUR, #hours,
DATEADD(DAY, #days,
DATEADD(WEEK, #weeks,
DATEADD(MONTH, #months,
DATEADD(YEAR, #years, end_datetime)))))))
FROM
Date_Ranges
WHERE
DATEADD(SECOND, 1, end_datetime) < #max_datetime
)
SELECT
DR.min_datetime,
DR.max_datetime,
AVG([Open]),
AVG([Close]),
AVG([Min]),
AVG([Max])
FROM
Date_Ranges DR
LEFT OUTER JOIN Quote_History QH ON
QH.id BETWEEN DR.min_datetime AND DR.max_datetime
GROUP BY
DR.min_datetime,
DR.max_datetime
ORDER BY
DR.min_datetime,
DR.max_datetime
You might need to fiddle with how to handle the edge cases (that 1 second range between date ranges could be a problem depending on your data). This should hopefully point you in the right direction though.
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)