I have a mysql table in which I want to group count of data in a month from last 12 months
example :
count(*) | months
12 | AUG 2022
11 | JULY 2022
0 | JUNE 2022
12 | AUG 2022
.
.
.
etc
last 12 months
and if no data in a particular month then mark It as zero
and i want last 12 months data from current month
data in in format of:
id | data | datetime
1 | somedata| 2017-11-23 00:45:54
2 | somedata| 2017-11-23 00:45:54
3 | somedata| 2017-10-23 00:45:54
4 | somedata| 2017-09-23 00:45:54
.
.
.
is this possible in MySQL and how?
Try with this one. Please replace DemoTable with your correct table.
Select DATE_FORMAT(last_12_months.date, '%Y-%m') AS year_and_month, count(data_table.id) as count
from (
SELECT (now() + interval 1 day - interval 11 month) date FROM dual union
SELECT (now() + interval 1 day - interval 10 month) date FROM dual union
SELECT (now() + interval 1 day - interval 9 month) date FROM dual union
SELECT (now() + interval 1 day - interval 8 month) date FROM dual union
SELECT (now() + interval 1 day - interval 7 month) date FROM dual union
SELECT (now() + interval 1 day - interval 6 month) date FROM dual union
SELECT (now() + interval 1 day - interval 5 month) date FROM dual union
SELECT (now() + interval 1 day - interval 4 month) date FROM dual union
SELECT (now() + interval 1 day - interval 3 month) date FROM dual union
SELECT (now() + interval 1 day - interval 2 month) date FROM dual union
SELECT (now() + interval 1 day - interval 1 month) date FROM dual union
SELECT now() month FROM dual
) last_12_months Left JOIN
DemoTable data_table
on DATE_FORMAT(data_table.dateTime, '%Y-%m') = DATE_FORMAT(last_12_months.date, '%Y-%m')
group by DATE_FORMAT(last_12_months.date, '%Y-%m') ;
Currently I'm using the below code:
SELECT DATE_SUB(example, INTERVAL 1 DAY) ,
FORMAT_DATE("%A", DATE_SUB(example, INTERVAL 1 DAY))
FROM UNNEST(GENERATE_DATE_ARRAY('2013-01-1', '2030-04-01', INTERVAL 3 MONTH)) AS example
The output which I'm getting is:
2012-12-31 Monday
2013-03-31 Sunday
2013-06-30 Sunday
2013-09-30 Monday
2013-12-31 Tuesday
2014-03-31 Monday
2014-06-30 Monday
2014-09-30 Tuesday
The expected output is:
2012-12-31 Monday
2013-03-29 Friday
2013-06-28 Friday
2013-09-30 Monday
2013-12-31 Tuesday
2014-03-31 Monday
2014-06-30 Monday
2014-09-30 Tuesday
I'm trying to extract the last working day for each quarter(3 months of timegap). But i couldn't exclude saturdays and sundays.
It would be great if someone help me to sort out this issue.
try this.
SELECT case when FORMAT_DATE("%A", DATE_SUB(example, INTERVAL 1 DAY)) = 'Sunday'
then date_sub(DATE_SUB(example, INTERVAL 1 DAY), interval 2 day)
when FORMAT_DATE("%A", DATE_SUB(example, INTERVAL 1 DAY)) = 'Saturday'
then date_sub(DATE_SUB(example, INTERVAL 1 DAY), interval 1 day)
else DATE_SUB(example, INTERVAL 1 DAY) end as d1,
case when FORMAT_DATE("%A", DATE_SUB(example, INTERVAL 1 DAY)) in ('Saturday','Sunday')
then 'Friday'
else FORMAT_DATE("%A", DATE_SUB(example, INTERVAL 1 DAY)) end
FROM UNNEST(GENERATE_DATE_ARRAY('2013-01-1', '2030-04-01', INTERVAL 3 MONTH)) AS example
order by d1
Try using this in your query ORDER BY your_date ASC
Consider below approach
create temp function getLastBusinessDayOfMonth(next_month_first_day date) as ((
select as struct month_last_business_day,
format_date("%A", month_last_business_day) day_of_week
from unnest([struct(next_month_first_day - 1 as month_last_day, extract(dayofweek from next_month_first_day) as adjust)]),
unnest([struct(month_last_day - if(adjust > 2, 0, adjust) as month_last_business_day)])
));
select getLastBusinessDayOfMonth(sample).*
from unnest(generate_date_array('2013-01-1', '2014-11-01', interval 3 month)) as sample
with output
You also can calculate the diffenece to the last workday with ELT().
This function returns the difference, in days, to the last workday
ELT(dayofweek(example), '2','3','1','1','1','1','1')
Sample for MariaDB
SELECT
example as org
, example - INTERVAL ELT(dayofweek(example), '2','3','1','1','1','1','1') DAY AS LAST_WORKDAY
, DATE_FORMAT(example - INTERVAL ELT(dayofweek(example), '2','3','1','1','1','1','1') DAY,'%W') AS WEEKDAY
FROM (
SELECT date('2013-01-01') + interval seq MONTH as example from seq_0_to_4) as d;
Sample for MySQL
SELECT
example as org
, example - INTERVAL ELT(dayofweek(example), '2','3','1','1','1','1','1') DAY AS LAST_WORKDAY
, DATE_FORMAT(example - INTERVAL ELT(dayofweek(example), '2','3','1','1','1','1','1') DAY,'%W') AS WEEKDAY
FROM UNNEST(GENERATE_DATE_ARRAY('2013-01-1', '2030-04-01', INTERVAL 3 MONTH)) AS example;
Result
MariaDB [bernd]> SELECT
-> example as org
-> , example - INTERVAL ELT(dayofweek(example), '2','3','1','1','1','1','1') DAY AS LAST_WORKDAY
-> , DATE_FORMAT(example - INTERVAL ELT(dayofweek(example), '2','3','1','1','1','1','1') DAY,'%W') AS WEEKDAY
-> FROM (
-> SELECT date('2013-01-01') + interval seq MONTH as example from seq_0_to_4) as d ;
+------------+--------------+----------+
| org | LAST_WORKDAY | WEEKDAY |
+------------+--------------+----------+
| 2013-01-01 | 2012-12-31 | Monday |
| 2013-02-01 | 2013-01-31 | Thursday |
| 2013-03-01 | 2013-02-28 | Thursday |
| 2013-04-01 | 2013-03-29 | Friday |
| 2013-05-01 | 2013-04-30 | Tuesday |
+------------+--------------+----------+
5 rows in set (0.001 sec)
MariaDB [bernd]>
I've been trying to solve this problem for a few hours , so far what i have reached is something like this:
SELECT * FROM mytable WHERE DATE(datetime_column)
BETWEEN DATE_SUB(DATE_FORMAT(NOW(),'%Y-%M-01'),INTERVAL 1 DAY) AND NOW()
AND HOUR(datetime_column) > = '13'
ORDER BY
datetime_column
Besides the day interval, i also need the hour interval which must be between 13h pm from last day of the last month till midday for present date.
The fiddle doesnt seem to work with the current query but its working in my database, but check fiddle for more info:
https://www.db-fiddle.com/f/a3jui7aPMevU81Cka4BqXg/0
And sample data:
CREATE TABLE mytable (
id INT,
datetime_column DATETIME
);
INSERT INTO mytable (id,datetime_column) VALUES
(1,'2020-03-31 08:00:00'),
(2,'2020-03-31 13:00:00'),
(3,'2020-04-02 14:30:00'),
(4,'2020-04-06 18:00:00'),
(5,'2020-04-21 05:00:00'),
(6,'2020-04-23 13:00:00'),
(7,'2020-04-23 14:00:00');
If more info is necessary please let me know.
I think this what you want
SELECT * FROM mytable
WHERE (
DATE(datetime_column) > LAST_DAY(CURDATE() - INTERVAL 1 MONTH)
AND datetime_column < (CURDATE() + INTERVAL 12 HOUR)
)
OR (
DATE(datetime_column) = LAST_DAY(CURDATE() - INTERVAL 1 MONTH)
AND HOUR(datetime_column) >= 13
);
+------+---------------------+
| id | datetime_column |
+------+---------------------+
| 2 | 2020-03-31 13:00:00 |
| 3 | 2020-04-02 14:30:00 |
| 4 | 2020-04-06 18:00:00 |
| 5 | 2020-04-21 05:00:00 |
+------+---------------------+
2 rows in set (0.00 sec)
Here LAST_DAY(CURDATE() - INTERVAL 1 MONTH) gives the last day of previous month.
And datetime_column < (CURDATE() + INTERVAL 12 HOUR) tests if that time is before mid day of today.
I have a table like so
+---------+
| weekday |
+---------+
| 2 |
| 5 |
| 3 |
+---------+
Now I want to have a resultset in which I see the dates of this and the upcoming week like so:
+------------+---------+
| date | weekday |
+------------+---------+
| 2019-12-18 | 2 |
| 2019-12-21 | 5 |
| 2019-12-19 | 3 |
| 2019-12-25 | 2 |
| 2019-12-28 | 5 |
| 2019-12-26 | 3 |
+------------+---------+
So far I have this query
SELECT
CURDATE() + INTERVAL w.weekday - WEEKDAY(CURDATE()) DAY AS thisWeek,
CURDATE() + INTERVAL w.weekday + 7 - WEEKDAY(CURDATE()) DAY AS nextWeek,
dw.weekday
FROM
weekdays AS w
Which gives me this result
+------------+------------+---------+
| thisWeek | nextWeek | weekday |
+------------+------------+---------+
| 2019-12-18 | 2019-12-25 | 2 |
| 2019-12-21 | 2019-12-28 | 5 |
| 2019-12-19 | 2019-12-26 | 3 |
+------------+------------+---------+
How would I have to need to proceed to get the former resultset?
Use UNION ALL.
SELECT
CURDATE() + INTERVAL w.weekday - WEEKDAY(CURDATE()) DAY AS date
dw.weekday
FROM
weekdays AS w
UNION ALL
SELECT
CURDATE() + INTERVAL w.weekday + 7 - WEEKDAY(CURDATE()) DAY AS date
dw.weekday
FROM
weekdays AS w;
You could try using UNION
select thisWeek date, weekday
from (
SELECT
CURDATE() + INTERVAL w.weekday - WEEKDAY(CURDATE()) DAY AS thisWeek,
CURDATE() + INTERVAL w.weekday + 7 - WEEKDAY(CURDATE()) DAY AS nextWeek,
dw.weekday
FROM weekdays AS w
) t1
union all
select nextWeek date, weekday
from (
SELECT
CURDATE() + INTERVAL w.weekday - WEEKDAY(CURDATE()) DAY AS thisWeek,
CURDATE() + INTERVAL w.weekday + 7 - WEEKDAY(CURDATE()) DAY AS nextWeek,
dw.weekday
FROM weekdays AS w
) t2
or for avoid subquery you could create a view
create view my_view as
SELECT
CURDATE() + INTERVAL w.weekday - WEEKDAY(CURDATE()) DAY AS thisWeek,
CURDATE() + INTERVAL w.weekday + 7 - WEEKDAY(CURDATE()) DAY AS nextWeek,
dw.weekday
FROM weekdays
then the query is
select thisWeek date, weekday
from my_view
union all
select nextWeek date, weekday
from my_view
I want to count records hourly in last 12 hours from my mysql table.
I found this link but my problem is, let say currently it's January 7 2016, 9 AM then i would like to count records from 7th Jan 9AM to Jan 6th 9PM.
My table structure is as following:
Table name :: cebod_cdr
id|userid|starting_date|total_duration
1 | 17 | 2016-01-07 09:00:00 | 12
2 | 17 | 2016-01-07 07:30:24 | 45
3 | 17 | 2016-01-07 01:12:21 | 5
4 | 17 | 2016-01-06 10:30:00 | 18
5 | 17 | 2016-01-06 10:45:00 | 25
Example output
hour | calls
9AM | 1
8AM | 0
7AM | 1
6AM | 0
5AM | 0
4AM | 0
3AM | 0
2AM | 0
1AM | 1
12AM | 0
11PM | 0
10PM | 2
If there is any problem in displaying hours in desired format(1-12), i can display it in some other format like 24 hours format etc.
SELECT HOUR(starting_date) AS Hour, COUNT(*) AS calls
FROM cebod_cdr
WHERE starting_date > DATE_ADD(NOW(), INTERVAL -12 HOUR)
GROUP BY HOUR(starting_date)
I have found the answer as below:
SELECT za_hours.za_hour as hour, COUNT(id) as calls
FROM (
SELECT NOW() - INTERVAL 1 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 2 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 3 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 4 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 5 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 6 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 7 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 8 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 9 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 10 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 11 HOUR as za_hour UNION
SELECT NOW() - INTERVAL 12 HOUR as za_hour )
za_hours
LEFT JOIN
cebod_cdr
ON DATE_FORMAT(za_hours.za_hour, '%Y-%m-%d %H:') = DATE_FORMAT(starting_date, '%Y-%m-%d %H:')
AND starting_date >= NOW() - INTERVAL 12 HOUR
GROUP BY za_hours.za_hour
ORDER BY za_hours.za_hour
Please suggest if i can improve this query.
Try this:
SELECT
date_format(dh.starting_date, '%Y-%m-%d %H:%i:%s') as hour,
COUNT(md.id) AS count
FROM
cebod_cdr dh
LEFT JOIN cebod_cdr md ON dh.starting_date = DATE_FORMAT(md.starting_date, '%Y-%m-%d %H:00:00')
WHERE dh.starting_date >= DATE_SUB(NOW(),INTERVAL 12 HOUR)
AND dh.starting_date < NOW()
GROUP BY dh.starting_date
ORDER BY dh.starting_date