Hourly counting MySQL - mysql

Since few days, I am trying to count records per hour from the MySQL database.
I have a table with a lot of records and I have column DATE and column TIME where in DATE I have the date of the record in the format 2022-05-19, and in the column TIME, I have the time of the record in the format 14:59:38.
What I am trying is to count every single day how many records per hour I have. Something like this:
DATE HOUR PCS
22-05-18 06-07 11
22-05-18 08-09 20
......... ..... ..
....... 21-22 33
I have tried many different ways but no success.
For example:
SELECT 'Date', count(*) FROM `root4`
where
DATE between '2022-05-01' and '2022-05-1' AND
TIME BETWEEN '06:11:05' AND '07:11:05'
Any help is highly evaluated.

I would recommend not using reserved words for columns, as you will have to escape them a lot. https://dev.mysql.com/doc/refman/8.0/en/keywords.html
If you stored TIME as a timestamp, you can extract the hour using the HOUR() function and group by that:
SELECT
`DATE`,
HOUR(`TIME`) AS `HOUR`,
COUNT(1)
FROM your_table
GROUP BY
`DATE`,
HOUR(`TIME`)
If you happened to store it as text you can use REGEXP_SUBSTR to get the hour value from your time string.
SELECT
`DATE`,
CAST(REGEXP_SUBSTR(`TIME`, '[0-9]+') AS UNSIGNED) AS `HOUR`,
COUNT(1)
FROM your_table
GROUP BY
`DATE`,
CAST(REGEXP_SUBSTR(`TIME`, '[0-9]+') AS UNSIGNED)
You can format your HOUR column how you want, like displaying 01-02 instead of 1 by using CONCAT, but this is your basic setup.

Related

Is there a flexible way to specify ranges of dates?

I am working with MySQL.
I have some queries that begin like this:
WITH dates (start_date, end_date) AS (
SELECT '2020-11-01', '2020-11-02'
UNION ALL SELECT '2020-11-02', '2020-11-03',
UNION ALL SELECT '2020-11-03', '2020-11-04')
SELECT dates.start_date, dates.end_date, id, COUNT(*)
FROM dates
INNER JOIN ...
I also sometimes need to run the same query, but with each date range being a week (Monday to Sunday), or a calendar month. Moreover, sometimes there are 100 or more of these, which is quite prone to typos in addition to occupying a lot of lines and taking a long time to write.
Is there more elegant and flexible way to achieve this ? Ideally I would like to be able to just specify a overall start date, an overall end date and a period (daily, weekly, monthly, yearly etc)
You can use a recursive CTE:
with recursive dates as (
select date('2020-11-01') as start_date, date('2020-11-02') as end_date
union all
select start_date + interval 1 day, end_date + interval 1 day
from dates
where start_date < '2020-12-01'
)
select *
from dates;
Here is a db<>fiddle. Of course, the logic would be a little different for months.
Create some date_ranges table which stores: series identifier, range number, range boundaries.
Insert needed series into it each time when you need a series which is not present in this table yet.
Use this table as source table in your query (maybe with additional condition which narrows the range if needed).
Remove series which will be used never in future.

How to return zero values if nothing was written in time interval?

I am using the Graph Reports for the select below. The MySQL database only has the active records in the database, so if no records are in the database from X hours till Y hours that select does not return anything. So in my case, I need that select return Paypal zero values as well even the no activity was in the database. And I do not understand how to use the UNION function or re-create select in order to get the zero values if nothing was recorded in the database in time interval. Could you please help?
select STR_TO_DATE ( DATE_FORMAT(`acctstarttime`,'%y-%m-%d %H'),'%y-%m-%d %H')
as '#date', count(*) as `Active Paid Accounts`
from radacct_history where `paymentmethod` = 'PayPal'
group by DATE_FORMAT(`#date`,'%y-%m-%d %H')
When I run the select the output is:
Current Output
But I need if there are no values between 2016-07-27 07:00:00 and 2016-07-28 11:00:00, then in every hour it should show zero active accounts Like that:
Needed output with no values every hour
I have created such select below , but it not put to every hour the zero value like i need. showing the big gap between the 12 Sep and 13 Sep anyway, but there should be the zero values every hour
(select STR_TO_DATE ( DATE_FORMAT(acctstarttime,'%y-%m-%d %H'),'%y-%m-%d %H')
as '#date', count(paymentmethod) as Active Paid Accounts
from radacct_history where paymentmethod <> 'PayPal'
group by DATE_FORMAT(#date,'%y-%m-%d %H'))
union ALL
(select STR_TO_DATE ( DATE_FORMAT(acctstarttime,'%y-%m-%d %H'),'%y-%m-%d %H')
as '#date', 0 as Active Paid Accounts
from radacct_history where paymentmethod <> 'PayPal'
group by DATE_FORMAT(#date,'%y-%m-%d %H')) ;
I guess, you want to return 0 if there is no matching rows in MySQL. Here is an example:
(SELECT Col1,Col2,Col3 FROM ExampleTable WHERE ID='1234')
UNION (SELECT 'Def Val' AS Col1,'none' AS Col2,'' AS Col3) LIMIT 1;
Updated the post: You are trying to retrieve data that aren't present in the table, I guess in reference to the output provided. So in this case, you have to maintain a date table to show the date that aren't in the table. Please refer to this and it's little bit tricky - SQL query that returns all dates not used in a table
You need an artificial table with all necessary time intervals. E.g. if you need daily data create a table and add all day dates e.g. start from 1970 till 2100.
Then you can use the table and LEFT JOIN your radacct_history. So for each desired interval you will have group item (group by should be based on the intervals table.

MYSQL Grouping timestamps by day when retrieving

i have thousands of timestamps, is it possible to get MySQL to sort these into a day / count array? Rather then doing it via PHP or JS.
The basic query is basically
$mysqli->query("SELECT datetime FROM `users` WHERE `datetime`");
And i need to present them on to a chart that takes date / count values. Id like to display it in a daily interval.
select date(datetime) as `day`, count(*)
from your_table
group by date(datetime)

How to write mysql select to get daily peaks

I have 'table' where i store 'rate' values every 30 minutes ('date' field). I want to get each day maximums (peaks). How can I select with one mysql request? Thanx...
SELECT MAX(rate) FROM 'table' GROUP BY DAY(date)
Should work for you :)
If the date field is a Unix timestamp, try:
SELECT time, MAX(data) FROM table GROUP BY DAY(FROM_UNIXTIME(time))

Is it possible to group rows by a day stored within a timestamp?

I'm not sure if this is even within the scope of MySQL to be honest or if some php is necessary here to parse the data. But if it is... some kind of stored procedure is likely necessary.
I have a table that stores rows with a timestamp and an amount.
My query is dynamic and will be searching based on a user-provided date range. I would like to retrieve the SUM() of the amounts for each day in a table that are between the date range. including a 0 if there are no entries for a given day
Something to the effect of...
SELECT
CASE
WHEN //there are entries present at a given date
THEN SUM(amount)
ELSE 0
END AS amountTotal,
//somehow select the day
FROM thisTableName T
WHERE T.timeStamp BETWEEN '$start' AND '$end'
GROUP BY //however I select the day
This is a two parter...
is there a way to select a section of a returned column? Like some kind of regex within mysql?
Is there a way to return the 0's for dates with no rows?
select * from thisTableName group by date(created_at);
In your case, it would be more like
SELECT id, count(id) as amountTotal
FROM thisTableName
WHERE timeStamp BETWEEN '$start' AND '$end'
GROUP BY DATE(timeStamp);
Your question is a duplicate so far: link.