Last hour wise count from 00 AM to last hour - mysql - mysql

I trying to fetch count of records from 00 AM i.e. 12 to last hour group by Hours.
select count(RESPONSE) AS TOTAL_521_ERROR from Sale_GT
where ERRORCODE='521'
AND SALEDATE > DATE_SUB(NOW(),INTERVAL 1 HOUR);
This query fetching last one hour record. similary I want if i run query at 5 AM then result should be count(RESPONSE) from 00 AM to 4 AM group by HOUR(SALEDATE).
Hour Count
0 345
1 432
2 36
3 87
4 90
so result will be from 12 night to last hour of query execution time.
Please help.

You can use SELECT with GROUP BY, e.g.:
SELECT HOUR(SALEDATE) AS `hour`, COUNT(RESPONSE) AS `errors`
FROM Sale_GT
WHERE ERRORCODE='521'
AND SALEDATE >= DATE(NOW())
GROUP BY `hour`;

Related

MySQL Select data from table with dates between in reverse of interval 7 days

I have a MySQL requirement to select data from a table based on a start date and end date and group it by weekly also selecting the data in reverse order by date. Assume that, I have chosen the start date as 1st November and the end date as 04 December. Now, I would like to fetch the data as 04 December to 28 November, 27 November to 20 November, 19 November to 12 November and so on and sum the value count for that week.
Given an example table,
id
value
created_at
1
10
2021-10-11
2
13
2021-10-17
3
11
2021-10-25
4
8
2021-11-01
5
1
2021-11-10
6
4
2021-11-18
7
34
2021-11-25
8
17
2021-12-04
Now the result should be like 2021-12-04 to 2021-11-28 as one week, following the same in reverse order and summing the column value data for that week. I have tried in the query to add the interval of 7 days after the end date but it didn't work.
SELECT count(value) AS total, MIN(R.created_at)
FROM data_table AS D
WHERE D.created_at BETWEEN '2021-11-01' AND '2021-12-04' - INTERVAL 7 DAY ORDER BY D.created_at;
And it's also possible to have the last week may have lesser than 7 days.
Expected output:
end_interval
start_interval
total
2021-12-04
2021-11-27
17
2021-11-27
2021-11-20
34
2021-11-20
2021-11-13
4
2021-11-13
2021-11-06
1
2021-11-06
2021-10-30
8
2021-10-30
2021-10-25
11
Note that the last week is only 5 days depending upon the selected from and end dates.
One option to address this problem is to
generate a calendar of all your intervals, beginning from last date till first date, with a split of your choice, using a recursive query
joining back the calendar with the original table
capping start_interval at your start_date value
aggregating values for each interval
You can have three variables to be set, to customize your date intervals and position:
SET #start_date = DATE('2021-10-25');
SET #end_date = DATE('2021-12-04');
SET #interval_days = 7;
Then use the following query, as already described:
WITH RECURSIVE cte AS (
SELECT #end_date AS end_interval,
DATE_SUB(#end_date, INTERVAL #interval_days DAY) AS start_interval
UNION ALL
SELECT start_interval AS end_interval,
GREATEST(DATE(#start_date), DATE_SUB(start_interval, INTERVAL #interval_days DAY)) AS start_interval
FROM cte
WHERE start_interval > #start_date
)
SELECT end_interval, start_interval, SUM(_value) AS total
FROM cte
LEFT JOIN tab
ON tab.created_at BETWEEN start_interval AND end_interval
GROUP BY end_interval, start_interval
Check the demo here.

Query to find the records creating in last 30 mins and then the records created in last 1 hour

I have a db of items from which I need to find the ones that were created in the last 30 mins, and want to order them by their category, then I want items that were created in the last 1 hour but I want to exclude the items found before, and again I want to order them by their category.
The current method I am using is using a union. I am not very sure if this is the best way. Something in my gut tells me there is a better way to do this, just don't know how.
Here's an example set of data and the query
id category_id created_at
1 1 10 mins ago
2 1 12 mins ago
3 2 10 mins ago
4 2 14 mins ago
5 1 40 mins ago
6 2 43 mins ago
7 1 34 mins ago
(select * from items where created_at >= NOW() - 30 mins order by category_id) union (select * from items where created_at >= NOW() - 60 mins and created_at < NOW() - 30 mins order by category_id)
The sample query is not syntactically correct obviously.
Create table
create table items (id int(11), category_id int(11), created_at datetime);
Output:
id category_id created_at
1 1 10 mins ago
2 1 12 mins ago
3 2 10 mins ago
4 2 14 mins ago
5 1 40 mins ago
7 1 43 mins ago
6 2 34 mins ago
Your idea is correct, but the proper syntax is this:
SELECT "last 30 minutes" as t, category_id, count(*) as cnt
FROM items
WHERE created_at >= NOW() - INTERVAL 30 MINUTE
GROUP BY category_id
UNION ALL
SELECT "last 1 hour" as t, category_id, count(*) as cnt
FROM items
WHERE
created_at < NOW() - INTERVAL 30 MINUTE
AND created_at >= NOW() - INTERVAL 60 MINUTE
GROUP BY category_id
...etc...
This query will count the events in the last 30 minutes, grouped by category_id, and then all events in the last hour but not in the last 30 minutes.
UNION ALL
is better than UNION on this context because UNION will return unique rows.
Edit
Based on your updated question, I think you are looking for this:
SELECT items.*
FROM items
WHERE created_at>=NOW() - INTERVAL 60 MINUTE
ORDER BY
(created_at >= NOW() - INTERVAL 30 MINUTE) DESC,
category_id
if you have more intervals then you can use this:
SELECT items.*
FROM items
WHERE created_at>=NOW() - INTERVAL 120 MINUTE
ORDER BY
(created_at >= NOW() - INTERVAL 30 MINUTE) DESC,
(created_at >= NOW() - INTERVAL 60 MINUTE) DESC,
category_id

Summing data for last 7 day look back window

I want a query that can give result with sum of last 7 day look back.
I want output date and sum of last 7 day look back impressions for each date
e.g. I have a table tblFactImps with below data:
dateFact impressions id
2015-07-01 4022 30
2015-07-02 4021 33
2015-07-03 4011 34
2015-07-04 4029 35
2015-07-05 1023 39
2015-07-06 3023 92
2015-07-07 8027 66
2015-07-08 2024 89
I need output with 2 columns:
dateFact impressions_last_7
query I got:
select dateFact, sum(if(datediff(curdate(), dateFact)<=7, impressions,0)) impressions_last_7 from tblFactImps group by dateFact;
Thanks!
If your fact table is not too big, then a correlated subquery is a simple way to do what you want:
select i.dateFact,
(select sum(i2.impressions)
from tblFactImps i2
where i2.dateFact >= i.dateFact - interval 6 day
) as impressions_last_7
from tblFactImps i;
You can achieve this by LEFT OUTER JOINing the table with itself on a date range, and summing the impressions grouped by date, as follows:
SELECT
t1.dateFact,
SUM(t2.impressions) AS impressions_last_7
FROM
tblFactImps t1
LEFT OUTER JOIN
tblFactImps t2
ON
t2.dateFact BETWEEN
DATE_SUB(t1.dateFact, INTERVAL 6 DAY)
AND t1.dateFact
GROUP BY
t1.dateFact;
This should give you a sliding 7-day sum for each date in your table.
Assuming your dateFact column is indexed, this query should also be relatively fast.

Select Rows where Day number is less than Given Threshold

I have a timestamp column. Say I want to get the rows where the day number in the year is < 50
Where Jan 1 = 1 and Dec 31 = 366
So the function is not year specific, I want to get the results between a day range e.g. 50 and 100 for all years.
Example
Timestamp
2012-02-01
2011-02-01
2012-04-01
So retrieving those results where DAY < 50 would return results: 1 and 2 but NOT 3.
You can use the DAYOFYEAR() function against the timestamp column in your WHERE clause:
SELECT *
FROM tbl
WHERE DAYOFYEAR(timestamp_col) < 50
Since day 50 occurs before February 29, there won't be any leap year considerations.
Try this:
SELECT * FROM TableA
WHERE DAYOFYEAR(DateCol) < 50 -- for < 50
SELECT * FROM TableA
WHERE DAYOFYEAR(DateCol) between 50 and 100 --between a day range e.g. 50 and 100
You can use this:
SELECT TO_DAYS(yourdate) - TO_DAYS(CONCAT(YEAR(yourdate), '-01-01')) + 1

MySQL Query to select last record for each of the past 7 days

I'm trying to come up with a MySQL query to select the last record from each of the previous 7 days. If 1 of the previous 7 days is missing data, I would only get back 6 records. Here's what I have:
SELECT tracking.* FROM tracking
INNER JOIN
(SELECT MAX(lastChecked) AS maxLastChecked, id FROM tracking
WHERE lastChecked >= DATE_SUB(lastChecked, INTERVAL 7 DAY )
GROUP BY DAY(lastChecked)) as Lookup ON Lookup.id = tracking.id
WHERE tracking.propertyID = 1 ORDER BY tracking.lastChecked ASC LIMIT 7
Basically what this should do is select the final recorded entry for propertyID = 1 in the tracking table for each of the past 7 days (starting on today). However, this query is returning this to me (more than ONLY records within the last 7 days):
ID propertyID lastChecked value
2 1 2012-01-25 05:30:00 280
1 1 2012-01-26 12:34:02 268
5 1 2012-01-27 09:51:31 268
83 1 2012-02-13 00:01:07 276
Any help to fix this up would be greatly appreciated!
Try this query:
SELECT tracking.* FROM tracking
INNER JOIN
(SELECT MAX(lastChecked) AS maxLastChecked, id FROM tracking
WHERE DATEDIFF(lastChecked,NOW())<=7
GROUP BY DAY(lastChecked)) as Lookup ON Lookup.id = tracking.id
WHERE tracking.propertyID = 1 ORDER BY tracking.lastChecked ASC
I believe you should have a system date instead of "lastChecked" in this part:
DATE_SUB(lastChecked, INTERVAL 7 DAY )
Should be:
DATE_SUB(SYSDATE(), INTERVAL 7 DAY )
WHERE lastChecked >= DATE_SUB(lastChecked, INTERVAL 7 DAY )
This condition of your code is going to be true for every record as lastChecked is always greater than lastChecked -7.
So, if you need data of last 7 days replace it with
WHERE lastChecked >= DATE_SUB(SYSDATE(), INTERVAL 7 DAY )