I want to count amount of ID's for each month for the last half year, here is my query:
SELECT count(`Id`) FROM `items` WHERE MONTH(Created) = MONTH(CURRENT_DATE) UNION SELECT `count(`Id`) FROM `items` WHERE MONTH(Created) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH) UNION SELECT count(`Id`) FROM `items` WHERE MONTH(Created) = MONTH(CURRENT_DATE - INTERVAL 2 MONTH) UNION SELECT count(`Id`) FROM `items` WHERE MONTH(Created) = MONTH(CURRENT_DATE - INTERVAL 3 MONTH) UNION SELECT count(`Id`) FROM `items` WHERE MONTH(Created) = MONTH(CURRENT_DATE - INTERVAL 4 MONTH) UNION SELECT count(`Id`) FROM `items` WHERE MONTH(Created) = MONTH(CURRENT_DATE - INTERVAL 5 MONTH);`
Created is the time stamp of the created row.
My problem is getting the fourth, fifth and sixth months. Because they were created in 2013 (different year), my query can't get their result.
I would start with something like this:
SELECT MONTH(created), count(*)
FROM `items`
WHERE Created >= LAST_DAY(current_date() - INTERVAL 6 MONTH) + INTERVAL 1 DAY
GROUP BY MONTH(created)
Where LAST_DAY(current_date() - INTERVAL 6 MONTH) + INTERVAL 1 DAY will return the first day of the month where to start the count, you might also want to group by month and year:
SELECT DATE_FORMAT(created, '%Y-%m'), count(*)
FROM `items`
WHERE Created >= LAST_DAY(current_date() - INTERVAL 6 MONTH) + INTERVAL 1 DAY
GROUP BY DATE_FORMAT(created, '%Y-%m')
Related
I'm trying to get last 12 months data in Mysql using below query but i'm getting all the data not last 12 months data i gone through few of the post but helpful
My CreatedDate format is like '2020-04-17 12:03:59'
SELECT date_format(createdDate,'%m') as Month,
count(*) as count,
date_format(createdDate,'%Y') as Year
FROM tablename
WHERE DATE_ADD(Now(),INTERVAL- 12 MONTH)
GROUP BY Year,
Month
ORDER by Year desc,
Month desc;
and also need help you Insert 0 if no data found in that month.
You may use a calendar table here:
SELECT
cal.dt,
COUNT(t.createdDate) AS count
FROM
(
SELECT DATE_FORMAT(CURDATE(), '%Y-%m') AS dt UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 1 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 2 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 3 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 4 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 5 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 6 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 7 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 8 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 9 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 10 MONTH), '%Y-%m') UNION ALL
SELECT DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 11 MONTH), '%Y-%m')
) cal
LEFT JOIN tablename t
ON cal.dt = DATE_FORMAT(createdDate, '%Y-%m')
WHERE
t.createdDate >= DATE_SUB(CURDATE(), INTERVAL 12 MONTH)
GROUP BY
cal.dt
ORDER BY
cal.dt DESC;
In MySQL 8+, you can use a recursive CTE to generate the dates:
with recursive dates as (
select curdate() - interval (1 - day(curdate())) day as yyyymm, 1 as lev
union all
select yyyymm - interval 1 month, lev + 1
from dates
where lev < 12
)
select d.yyyymm, count(t.createdDate) as cnt
from dates d left join
tablename t
on t.createdDate >= d.yyyymm and
t.createdDate < d.yyyymm + interval 1 month
group by d.yyyymm;
Note that this doesn't split the year and month into separate columns, but you can do that if you really want.
Also, this provide the current month with partial data. You can adjust the logic if you only want complete months.
I'm trying to get values from dataTable for the last 7 days, if there is no data for specific date zero should be filled in the output:
SELECT calendar.dt, COALESCE(SUM(weight*price),0) AS amount
FROM
(SELECT CURRENT_DATE AS dt
UNION ALL SELECT CURRENT_DATE - INTERVAL 1 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 2 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 3 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 4 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 5 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 6 DAY) calendar
LEFT JOIN dataTable ON calendar.dt = DATE(dataTable.sold_at);
Request above returns only one record:
Please advise what is wrong with SQL request?
Seems that group by Is missing.
SELECT calendar.dt, COALESCE(SUM(weight*price),0) AS amount
FROM
(SELECT CURRENT_DATE AS dt
UNION ALL SELECT CURRENT_DATE - INTERVAL 1 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 2 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 3 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 4 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 5 DAY
UNION ALL SELECT CURRENT_DATE - INTERVAL 6 DAY) calendar
LEFT JOIN dataTable ON calendar.dt = DATE(dataTable.sold_at)
Group by calendar.dt
;
SQL fiddle link: http://sqlfiddle.com/#!9/f151a8e/4
i have the following mysql query , but its taking approx 5 minutes to execute, how can i decrease its execution time
select
revenue_center_group.description as rc_group,
revenue_center.description as revenue_center,
count(ytd.members) as total_ytd_members,
count(lytd.members) as total_lytd_members
from revenue_center
left join revenue_center_group on revenue_center_group.id = revenue_center.revenue_center_group_id
left join (
select membership.id as members,
membership.rc_id as rc_id
from membership
where membership.status =1
and DATE(membership.join_date)>= (SELECT DATE_FORMAT((SELECT DATE_FORMAT(date(now()) - INTERVAL 1 MONTH, '%Y-%m-%d')) ,'%Y-01-01 00:00:00'))
and DATE(membership.join_date)<= (SELECT DATE_FORMAT(LAST_DAY(date(now()) - INTERVAL 1 MONTH), '%Y-%m-%d 23:59:59'))ytd on revenue_center.id = ytd.rc_id
left join (
select
membership.id as members,
membership.rc_id as rc_id
from membership
where membership.status =1
and DATE(membership.join_date)>= (SELECT DATE_FORMAT((SELECT DATE_FORMAT((SELECT DATE_FORMAT(date(now()) - INTERVAL 1 MONTH, '%Y-%m-%d'))
- INTERVAL 1 YEAR, '%Y-%m-%d')) ,'%Y-01-01 00:00:00'))
and DATE(membership.join_date)<= (SELECT DATE_FORMAT((select DATE_FORMAT(LAST_DAY(date(now()) - INTERVAL 1 MONTH), '%Y-%m-%d')
- INTERVAL 1 YEAR),'%Y-%m-%d 23:59:59'))lytd on revenue_center.id = lytd.rc_id
group by revenue_center_group.description,revenue_center.description with rollup;
I'm using MySQL with PHP. Here is my query on which I'm getting the error.
$query =
"SELECT days.day, count(myDataTable.appId) as countf, count(myDataTable.appId) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id' AND n1.status = 'ERROR'
group by days.day
left join myDataTable as n2
on days.day = n2.date AND n2.appId = '$id' AND n2.status = 'SUCCESS'
group by days.day";
The error log is:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'left join myDataTable on days.day = myDataTable.date AND myDataTable.appId ' at line 17
It helps to properly indent your SQL so you can spot the mistakes. Indenting by the main keywords (SELECT, FROM, WHERE, HAVING, GROUP BY, and ORDER BY) will help you spot them quickly:
SELECT
days.day,
count (myDataTable.appId) as countf,
count(myDataTable.appId) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id' AND n1.status = 'ERROR'
group by
days.day
left join myDataTable as n2
on days.day = n2.date AND n2.appId = '$id' AND n2.status = 'SUCCESS'
group by
days.day
You can see that you have two GROUP BY's which won't work. Furthermore you have a LEFT JOIN hanging out in the first GROUP BY clause, which doesn't work either. Removing that first GROUP BY will get you closer:
SELECT
days.day,
count (myDataTable.appId) as countf,
count(myDataTable.appId) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id' AND n1.status = 'ERROR'
left join myDataTable as n2
on days.day = n2.date AND n2.appId = '$id' AND n2.status = 'SUCCESS'
group by
days.day
No you have a proper FROM clause. This is the first part that your Database looks at so it knows from where it is getting it's data and how it joins together. Your table aliases are set here and then used EVERYWHERE else in the query. Which leads you to the second problem.
You reference myDataTable up in your SELECT clause, but by the time the database is looking at your SELECT myDataTable isn't in context. The aliases n1 and n2 are though, so change these to reference your table aliases:
SELECT
days.day,
count (n1.appId) as countf,
count(n2.appId) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id' AND n1.status = 'ERROR'
left join myDataTable as n2
on days.day = n2.date AND n2.appId = '$id' AND n2.status = 'SUCCESS'
group by
days.day
Lastly, instead of joining your myDataTable in twice for each status, you can use a CASE statement in your SELECT:
SELECT
days.day,
SUM(CASE WHEN n1.status = 'ERROR' THEN 1 ELSE 0 END) as countf,
SUM(CASE WHEN n1.status = 'SUCCESS' THEN 1 ELSE 0 END) as counts
FROM
(
select curdate() as day
union select curdate() - interval 1 day
union select curdate() - interval 2 day
union select curdate() - interval 3 day
union select curdate() - interval 4 day
union select curdate() - interval 5 day
union select curdate() - interval 6 day
union select curdate() - interval 7 day
union select curdate() - interval 8 day
union select curdate() - interval 9 day
) days
left join myDataTable as n1
on days.day = n1.date AND n1.appId = '$id'
group by
days.day
We have a table with two fields tkTimeOpen and tkTimeClosed. We need to find the average wait time for this month and last month. I've been unable to get the right SQL query to pull out what I need.
This is how the date-time is recorded; 2017-01-25 10:35
This Month's Average;
SELECT SUM(DATEDIFF(MINUTE,tkTimeOpen,tkTimeClose)) * 1.0
/ (SELECT COUNT(*) * 1.0 FROM e_ticket)
FROM e_ticket
WHERE YEAR(tkTimeOpen) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND MONTH(tkTimeOpen) = MONTH(CURRENT_DATE - INTERVAL 0 MONTH)
Last Month's Average
SELECT SUM(DATEDIFF(MINUTE,tkTimeOpen,tkTimeClose)) * 1.0
/ (SELECT COUNT(*) * 1.0 FROM e_ticket)
FROM e_ticket
WHERE YEAR(tkTimeOpen) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH) AND MONTH(tkTimeOpen) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)
I've tried a lot of variations but it doesn't give the desired output.
If anyone could help that would be great!
Thank you
This should give you the average minutes for last month and this month combined:
SELECT AVG(TIMESTAMPDIFF(MINUTE, tkTimeOpen, tkTimeClose))
FROM e_ticket
WHERE tkTimeOpen >= DATE_ADD(LAST_DAY(DATE_SUB(NOW(), INTERVAL 2 MONTH)), INTERVAL 1 DAY);
If you still need to get the averages separately, you can keep your WHERE clause similar to what you have...
For this month:
SELECT AVG(TIMESTAMPDIFF(MINUTE, tkTimeOpen, tkTimeClose))
FROM e_ticket
WHERE YEAR(tkTimeOpen) = YEAR(NOW()) AND MONTH(tkTimeOpen) = MONTH(NOW());
And for last month:
SELECT AVG(TIMESTAMPDIFF(MINUTE, tkTimeOpen, tkTimeClose))
FROM e_ticket
WHERE YEAR(tkTimeOpen) = YEAR(NOW() - INTERVAL 1 MONTH) AND MONTH(tkTimeOpen) = MONTH(NOW() - INTERVAL 1 MONTH);
One function you could use is TIMESTAMPDIFF - not DATEDIFF
You can use AVG() instead of SUM() / COUNT()
SELECT AVG(TIMESTAMPDIFF(MINUTE,tkTimeOpen,tkTimeClose))
FROM e_ticket
WHERE YEAR(tkTimeOpen) = YEAR(CURRENT_DATE - INTERVAL 1 MONTH)
AND MONTH(tkTimeOpen) = MONTH(CURRENT_DATE - INTERVAL 1 MONTH)