I have a unique query request.
I run this query:
select * from documentationissues
where dateAdded is not null
and dateAdded >= '2013-10-09 10:37:15.483'
This will return me however many rows have been inserted since the dateAdded clause. What I am trying to do is do all of my math in the query as well.
I need to figure out how many minutes have passed since the dateAdded clause.
I need to get a count of how many rows that are returned.
I then need to figure out on average how many rows are being done on average per minute and then per hour.
And then say if there were 6,000,000 files to be done. How many days it would take to process all of the files at the average day rate.
If I ran the query right now it returned 2100 results as of today at 10:56:15 am.
So that would be 19 minutes have passed which is about 110 rows per minute and about 6600 per hour.
I'm not sure how to do all of the math in the select statement with grouping etc.
Here is another option that also includes all of the fields you were asking for:
SELECT M.RowsReturned, M.MinutesPassed,
M.RowsReturned / M.MinutesPassed AS AvgPerMinute,
M.RowsReturned / M.MinutesPassed * 60 AS AvgPerHour,
6000000 / M.RowsReturned / M.MinutesPassed / 1440 AS DaysToProcess
FROM (
SELECT COUNT(*) AS RowsReturned,
DATEDIFF(minute, '2013-10-09 10:37:15.483', CURRENT_TIMESTAMP) AS MinutesPassed
FROM documentationissues
WHERE dateAdded is NOT NULL
AND dateAdded >= '2013-10-09 10:37:15.483'
) AS M
Try this:
SELECT COUNT(*)/DATEDIFF(minute, '2013-10-09 10:37:15.483', GETDATE()) AS AvgPerMin,
COUNT(*)/DATEDIFF(minute, '2013-10-09 10:37:15.483', GETDATE()) * 60 AS AvgPerHr
from documentationissues
where dateAdded is not null
and dateAdded >= '2013-10-09 10:37:15.483'
Related
I am running the following query
select DateTime
from Calls
where DateTime > '17 Oct 2018 00:00:00.000' and
DialedNumberID = '1234'
What would this give me is a list of all the times that this number was dialled on the specific date.
Essentially what I am looking for is a query that would give me the average calls that take place every X minutes and would like to run the query for the whole year.
Thanks
I guess you have a table named Calls with the columns DateTime and DialedNumberID.
You can summarize the information in that table year-by-year using the kind of pattern.
SELECT YEAR(`DateTime`),
DialedNumberID,
COUNT(*) call_count
FROM Calls
GROUP BY YEAR(`DateTime`), DialedNumberID
The trick in this pattern is to GROUP BY f(date) . The function f() reduces any date to the year in which it occures.
Summary by five minute intervals, you need f(date) that reduces datestamps to five minute intervals. That function is a good deal more complex than YEAR().
DATE_FORMAT(datestamp,'%Y-%m-%d %H:00') + INTERVAL (MINUTE(datestamp) - MINUTE(datestamp) MOD 5)
Given, for example, 2001-09-11 08:43:00, this gives back 2001-09-11 08:40:00.
So, here's your summary by five minute intervals.
SELECT DATE_FORMAT(`DateTime`,'%Y-%m-%d %H:00')+INTERVAL(MINUTE(`DateTime`)-MINUTE(datestamp) MOD 5) interval_beginning,
DialedNumberID,
COUNT(*) call_count
FROM Calls
GROUP BY DATE_FORMAT(`DateTime`,'%Y-%m-%d %H:00')+INTERVAL(MINUTE(`DateTime`)-MINUTE(datestamp) MOD 5),
DialedNumberID
You can make this query clearer and less repetitive by defining a stored function for that ugly DATE_FORMAT() expression. But that's a topic for another day.
Finally, append
WHERE YEAR(`DateTime`) = YEAR(NOW())
AND DialedNumberID = '1234'
to the query to filter by the current year and a particular id.
This query will need work to make it as efficient as possible. That too is a topic for another day.
Pro tip: DATETIME is a reserved word in MySQL. Column names are generally case-insensitive. Avoid naming your columns, in this case DateTime, the same as a reserved word.
The average amount of calls per interval is the number of calls (COUNT(*)) divided by the minutes between the start and end of of the monitored period (TIMESTAMPDIFF(minute, period_start, period_end)) multiplied with the number of minutes in the desired interval (five in your example).
For MySQL:
select count(*) / timestampdiff(minute, date '2018-01-01', now()) * 5 as avg_calls
from calls
where `datetime` >= date '2018-01-01'
and dialednumberid = 1234;
For SQL Server:
select count(*) * 1.0 / datediff(minute, '20180101', getdate()) * 5 as avg_calls
from calls
where [datetime] >= '20180101'
and dialednumberid = 1234;
This forces the call time into 5 minute intervals. Use 'count' and 'group by' on these intervals. Using DateTime as a column name is confusing
SELECT DATEADD(MINUTE, CAST(DATEPART(MINUTE, [DateTime] AS INTEGER)%5 * - 1,CAST(FORMAT([DateTime], 'MM/dd/yyyy hh:mm') AS DATETIME)) AS CallInterval, COUNT(*)
FROM Calls
GROUP BY DATEADD(MINUTE, CAST(DATEPART(MINUTE, [DateTime]) AS INTEGER)%5 * - 1,CAST(FORMAT([DateTime], 'MM/dd/yyyy hh:mm') AS DATETIME))
I have a table that I'm trying to not only get the sum of time(hours) difference between two columns but also the amount of times a time difference is above a set amount, 6 in this case.
The total I got from Getting the sum of a datediff result but can I in the same query also get count(*) where datediff => 6?
Thanks in advance for any and all help.
DateDiff used for hours will probably not be useful, as it will return 1 hour from, say 10:55 to 11:03.
So count minutes:
Select
*, DateDiff("n", [TimeStart], [TimeEnd]) / 60 As Hours
From
YourTable
Save this query and use it as source in a new query to count those entries with an hour count greater than or equal to six:
Select Count(*) As Entries
From YourQuery
Where Hours >= 6
I have a table that stores time, heart_rate, and player_id. I need to somehow take an average of the heart rate data over the last five minutes and group each average by the player ID.
Another option is to use DATEDIFF
SELECT AVG(heart_rate) AS heart_rate,
player_id
FROM tablename
WHERE DATEDIFF(MINUTE, time, GETDATE()) < 5
GROUP BY player_id
This is partly a response to Donal's answer (and too long for a comment).
You do not want to use the following:
WHERE datepart(minute, (time - GETDATE())) < 5
There are two reasons. First, this cannot make use of an index on time. That is, the calculation is not sargable. Second, the subtraction is backwards, unless time values are in the future.
A better way to write this is:
select player_id, avg(heart_rate)
from table t
where time >= dateadd(minute, -5, getdate())
group by player_id;
I am trying to group some records into 5-, 15-, 30- and 60-minute intervals:
SELECT AVG(value) as "AvgValue",
sample_date/(5*60) as "TimeFive"
FROM DATA
WHERE id = 123 AND sample_date >= 3/21/2012
i want to run several queries, each would group my average values into the desired time increments. So the 5-min query would return results like this:
AvgValue TimeFive
6.90 1995-01-01 00:05:00
7.15 1995-01-01 00:10:00
8.25 1995-01-01 00:15:00
The 30-min query would result in this:
AvgValue TimeThirty
6.95 1995-01-01 00:30:00
7.40 1995-01-01 01:00:00
The datetime column is in yyyy-mm-dd hh:mm:ss format
I am getting implicit conversion errors of my datetime column. Any help is much appreciated!
Using
datediff(minute, '1990-01-01T00:00:00', yourDatetime)
will give you the number of minutes since 1990-1-1 (you can use the desired base date).
Then you can divide by 5, 15, 30 or 60, and group by the result of this division.
I've cheked it will be evaluated as an integer division, so you'll get an integer number you can use to group by.
i.e.
group by datediff(minute, '1990-01-01T00:00:00', yourDatetime) /5
UPDATE As the original question was edited to require the data to be shown in date-time format after the grouping, I've added this simple query that will do what the OP wants:
-- This convert the period to date-time format
SELECT
-- note the 5, the "minute", and the starting point to convert the
-- period back to original time
DATEADD(minute, AP.FiveMinutesPeriod * 5, '2010-01-01T00:00:00') AS Period,
AP.AvgValue
FROM
-- this groups by the period and gets the average
(SELECT
P.FiveMinutesPeriod,
AVG(P.Value) AS AvgValue
FROM
-- This calculates the period (five minutes in this instance)
(SELECT
-- note the division by 5 and the "minute" to build the 5 minute periods
-- the '2010-01-01T00:00:00' is the starting point for the periods
datediff(minute, '2010-01-01T00:00:00', T.Time)/5 AS FiveMinutesPeriod,
T.Value
FROM Test T) AS P
GROUP BY P.FiveMinutesPeriod) AP
NOTE: I've divided this in 3 subqueries for clarity. You should read it from inside out. It could, of course, be written as a single, compact query
NOTE: if you change the period and the starting date-time you can get any interval you need, like weeks starting from a given day, or whatever you can need
If you want to generate test data for this query use this:
CREATE TABLE Test
( Id INT IDENTITY PRIMARY KEY,
Time DATETIME,
Value FLOAT)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:00:22', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:03:22', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:04:45', 10)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:07:21', 20)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:10:25', 30)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:11:22', 30)
INSERT INTO Test(Time, Value) VALUES('2012-03-22T00:14:47', 30)
The result of executing the query is this:
Period AvgValue
2012-03-22 00:00:00.000 10
2012-03-22 00:05:00.000 20
2012-03-22 00:10:00.000 30
Building on #JotaBe's answer (to which I cannot comment on--otherwise I would), you could also try something like this which would not require a subquery.
SELECT
AVG(value) AS 'AvgValue',
-- Add the rounded seconds back onto epoch to get rounded time
DATEADD(
MINUTE,
(DATEDIFF(MINUTE, '1990-01-01T00:00:00', your_date) / 30) * 30,
'1990-01-01T00:00:00'
) AS 'TimeThirty'
FROM YourTable
-- WHERE your_date > some max lookback period
GROUP BY
(DATEDIFF(MINUTE, '1990-01-01T00:00:00', your_date) / 30)
This change removes temp tables and subqueries. It uses the same core logic for grouping by 30 minute intervals but, when presenting the data back as part of the result I'm just reversing the interval calculation to get the rounded date & time.
So, in case you googled this, but you need to do it in mysql, which was my case:
In MySQL you can do
GROUP BY
CONCAT(
DATE_FORMAT(`timestamp`,'%m-%d-%Y %H:'),
FLOOR(DATE_FORMAT(`timestamp`,'%i')/5)*5
)
In the new SQL Server 2022, you can use DATE_BUCKET, this rounds it down to the nearest interval specified.
SELECT
DATE_BUCKET(minute, 5, d.sample_date) AS TimeFive,
AVG(d.value) AS AvgValue
FROM DATA d
WHERE d.id = 123
AND d.sample_date >= '20121203'
GROUP BY
DATE_BUCKET(minute, 5, d.sample_date);
You can use the following statement, this removed the second component and calculates the number of minutes away from the five minute mark and uses this to round down to the time block. This is ideal if you want to change your window, you can simply change the mod value.
select dateadd(minute, - datepart(minute, [YOURDATE]) % 5, dateadd(minute, datediff(minute, 0, [YOURDATE]), 0)) as [TimeBlock]
This will help exactly what you want
replace dt - your datetime c - call field astro_transit1 - your table 300 refer 5 min so add 300 each time for time gap increase
SELECT FROM_UNIXTIME( 300 * ROUND( UNIX_TIMESTAMP( r.dt ) /300 ) ) AS 5datetime, ( SELECT r.c FROM astro_transit1 ra WHERE ra.dt = r.dt ORDER BY ra.dt DESC LIMIT 1 ) AS first_val FROM astro_transit1 r GROUP BY UNIX_TIMESTAMP( r.dt ) DIV 300 LIMIT 0 , 30
How can i calculate average of each 30 second? The following is the table structure
Price TTime
every minute 5-60 records inserted. The time is inserted by getDate(). I have to calculate average of every 30 seconds.
You need to do 2 things:
Create a column (in your SELECT result, not in the table) that contains the time in half-minutes;
calculate the average of Price using AVG(Price) and GROUP BY:
SELECT <function returning half minutes from TTime> AS HalfMinute, AVG(Price) FROM <Table> GROUP BY HalfMinute`
I don't know SQL Server's time functions. If you can get the time returned in seconds, you could go with SECONDS/30. Maybe someone else can step in with details here.
Something like:
SELECT
AVG(Price) AS AvgPrice,
COUNT(Price) AS CountPrice,
MIN(TTIME) AS PeriodBegin,
(SECOND(TTime) % 30) * 30 AS PeriodType /* either 0 or 30 */
FROM
PriceTable
GROUP BY
YEAR(TTime), MONTH(TTime), DAY(TTime), HOUR(TTime), MINUTE(TTime)
SECOND(TTime) % 30 /* either 0 or 1 */
ORDER BY
MIN(TTime)
In place of:
GROUP BY
YEAR(TTime), MONTH(TTime), DAY(TTime), HOUR(TTime), MINUTE(TTime)
you could also use, for example:
GROUP BY
LEFT(CONVERT(varchar, TTime, 120), 16)
In any case these are operation that invoke a table scan, since they are not indexable. A WHERE clause to determine the valid TTime range is advisable.
You could also make a column that contains the calculated date ('…:00.000' or '…:30.000') and fill that on INSERT with help of a trigger. Place an index on it, GROUP BY it, done.