I have two MySQL tables, called "accounts" and "events".
Accounts
ID
name
1
Pete
2
Josh
3
Harry
Events
ID
date
account_id
1
2021-10-09
1
2
2021-09-25
1
3
2021-10-23
2
4
2021-11-06
1
5
2021-10-13
1
6
2021-11-17
2
7
2021-11-06
3
8
2021-12-04
3
The account_id in the events table is linked to the id in the accounts table.
My question is: which query can I use to count saturdays in each month (date YYYY-mm-dd format) for each unique user in the accounts table? So I get the next result:
Name
September
October
November
December
Josh
0
1
0
0
Pete
1
1
1
0
Harry
0
0
1
1
I've tried many queries (with i.e. the (inner) JOIN, DISTINCT and GROUP BY keywords) but I don't get the exact result. Can you please help me?
Many thanks in advance!
Basically you can use DAYOFWEEK function and GROUP BY MONTH
SELECT
account_id,
MONTH(date),
COUNT(*)
FROM Events
WHERE DAYOFWEEK(date) = 7
GROUP BY account_id, MONTH(date);
SQL Fiddle here
and when you can use PIVOT on received table like:
WITH res AS (
SELECT
account_id,
MONTH(date) mnth,
COUNT(*) cnt
FROM Events
WHERE DAYOFWEEK(date) = 7
GROUP BY account_id, MONTH(date)
) SELECT
account_id,
name,
SUM(mnth=1) Januar,
--
SUM(mnth=9) September,
SUM(mnth=10) October,
SUM(mnth=11) November,
SUM(mnth=12) December
FROM res
JOIN Accounts ON Accounts.id = account_id
GROUP BY account_id, name;
SQL Pivot Fiddle
Related
I want to fetch data of last two months of each category from table.
Table looks like:
Id
Year
month
category
value
1
2019
1
TEST1
10
2
2018
12
TEST1
10
3
2018
10
TEST1
10
4
2018
1
TEST2
10
5
2018
12
TEST2
10
6
2018
1
TEST3
10
Expected output:
Id
Year
month
category
value
1
2019
1
TEST1
10
2
2018
12
TEST1
10
5
2018
12
TEST2
10
4
2018
1
TEST2
10
6
2018
1
TEST3
10
I tried using:
SELECT a.year,a.month,a.value, a.category
FROM test_data AS a
WHERE
(
SELECT COUNT(*)
FROM test_data AS b
WHERE b.category = a.category AND (b.year >= a.year AND b.month >= a.month)) <= 2
ORDER BY a.year DESC, a.month DESC
But it is giving extra record of TEST1 category. I guess because it is not working as expected for year condition. Please provide solution for this
Your first effort should go into fixing your data model and using a date-like datatype to store the date information, rather than spreading it over different columns. This should be as simple as adding a new column to the table and updating it from the existing columns:
alter table test_data add mydate date;
update test_data set mydate = concat(year, '-', month, '-01');
That said, to make your current query work you need to fine-tune the conditions on the dates as follows. One option uses arithmetics:
SELECT a.year, a.month, a.value, a.category
FROM test_data AS a
WHERE (
SELECT COUNT(*)
FROM test_data AS b
WHERE
b.category = a.category
AND 100 * b.year + b.month >= 100 * a.year + a.month
) <= 2
ORDER BY a.year DESC, a.month DESC
Alternatively, if you are running MySQL 8.0, you can use row_number():
SELECT a.year, a.month, a.value, a.category
FROM (
SELECT
a.*,
ROW_NUMBER() OVER(PARTITION BY a.category ORDER BY a.year DESC, a.month DESC)
FROM test_data AS a
) a
WHERE rn <= 2
I have an issue. I am joining two table and can not get the proper data using MySQL.I am explaining my table below.
db_day:
day_id day_name
1 Monday
2 Tuesday
3 Wednesday
4 Thursday
5 Friday
6 Saturday
7 Sunday
db_images:
id name from_day to_day
1 Raj 1 3
2 Rahul 4 7
I am explaining my query below.
select sl.id,sl.name,sl.from_day,sl.to_day,d.day_name,d.day_id from db_images as sl left join db_day as d on d.day_id=sl.from_day sl.id desc
Here i need both from day and to day with the name after joining the table but here i am getting the from day only .Please help me to resolve this issue.
Join the db_day table twice with different alias names
select sl.id, sl.name, sl.from_day, sl.to_day,
d1.day_name as from_day, d1.day_id as from_id,
d2.day_name as to_day, d2.day_id as to_id
from db_images sl
left join db_day d1 on d1.day_id = sl.from_day
left join db_day d2 on d2.day_id = sl.to_day
I have a table as:
date passed failed subject
2015-2-1 2 1 maths
2015-2-1 3 2 cs
2015-3-1 1 2 maths
2015-12-1 2 1 maths
I have a form to select the start date and end date.
for eg:If I select startdate = 2015-2-1 and enddate=2015-3-1
my output should be:
date passed failed
2015-2-1 5 3
2015-3-1 1 2
output should contain the total no of passed and failed (irrespective of subjects) for same months as shown above.
This is the query which I used:
startdate=2015-2-1 and enddate=2015-3-1
SELECT SUM(passed) ,SUM(failed) FROM student_log WHERE
(DATE(`date`)='2015-2-1')
union
SELECT SUM(passed) ,SUM(failed) FROM student_log WHERE
(DATE(`date`)='2015-3-1')
It works fine But if my end date is December I should repeat my union query till December...
Please suggest an alternative.
What about:
SELECT SUM(passed), SUM(failed), DATE(`date`)
FROM student_log
WHERE DATE(`date`) >= '2015-2-1' AND DATE(`date`) <= '2015-3-1'
GROUP BY DATE(`date`);
This would find all tests between two dates and give you a count from each day.
You dont need separate queries or join or union for this
SELECT SUM(`pass`) as total_pass, SUM(`fail`) as total_fail
FROM pass_fail
WHERE (`date` = '2015-2-1' or `date` = '2015-3-1' )
GROUP BY `date`
Output
Refer Group By
this query :
Select date,sum (passed),sum(failed) from Results group by date
returns the following results for me :
date passed failed
2015-02-01 5 3
2015-03-01 1 2
2015-12-01 2 1
In other words: The group by clause will display the data per Month as you need it.
I have a visit table with user_id and visited_at columns. I would like to find how many are new and repeat customer in this month.
user_id visited_at
--------------------------------------------------------------------------
1750 2015-04-06 10:39:20
1870 2015-04-05 15:48:11
1990 2015-04-04 12:38:35
1920 2015-04-03 10:18:21
1080 2015-04-01 10:18:21
1750 2015-01-28 12:38:59
1920 2015-01-19 17:20:20
1920 2015-01-17 15:10:10
1080 2015-01-13 20:18:41
1920 2014-04-04 10:31:15
1750 2013-10-04 10:39:20
In January 2015, user 1750 and 1920 visited the same place so total repeated customers are 2. In April 2015, user 1750, 1920 and 1080 visited the same place so total repeated customers are 3. The output should be something like this
Month New Repeat
----------------------------------------------
October 2013 1 0
April 2014 1 0
January 2015 1 2
April 2015 2 3
One approach is to get the date of the first visit for each user using a subquery. Then join in this information, and use count(distinct) to count the number of users:
select year(v.visited_at) as yyyy, month(visited_at) as mm,
count(distinct user_id) as num_users,
count(case when v.visited_at = vv.minva then user_id end) as num_new_users
from visits v join
(select user_id, min(visited_at) as minva
from visits t
group by user_id
) vv
on v.user_id = vv.user_id
group by year(v.visited_at), month(visited_at)
order by year(v.visited_at), month(visited_at);
I note that this gives the total and new users; the repeats are the difference.
Something like this will work:
SELECT * FROM table_name WHERE updated_at >= CAST('2014-02-01' AS DATE) AND updated_at <= CAST('2014-02-28' AS DATE);
SELECT
MONTH(created_at) as _Month,
YEAR(created_at) as _Year,
COUNT(*) as New
FROM
yourtable
GROUP BY 0,1
You can also filter results using where clause.
I am generating mysql query to show the number of orders received in current month group by days of month.
The table structure of mysql is as follow:
order_id date
======== ==========
1234 2012-07-02
1235 2012-07-02
1236 2012-07-04
1237 2012-07-07
1238 2012-07-08
Now I want it to return following results using mysql statement
count(order_id) day
=============== ===
0 01
2 02
0 03
1 04
0 05
0 06
1 07
1 08
So on and so forth till the end of the month 30/31 depends on the days in month.
Looking forward to your suggestions and help.
Thanks.
SELECT
count(order_id),
dates.dte
FROM
(
SELECT '2011-02-01' + INTERVAL a + b DAY dte
FROM
(SELECT 0 a UNION SELECT 1 a UNION SELECT 2 UNION SELECT 3
UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7
UNION SELECT 8 UNION SELECT 9 ) d,
(SELECT 0 b UNION SELECT 10 UNION SELECT 20
UNION SELECT 30 UNION SELECT 40) m
WHERE '2011-02-01' + INTERVAL a + b DAY < '2011-03-01'
ORDER BY a + b
) dates
LEFT JOIN
orders ON orders.`date` = dates.dte
GROUP BY
dates.dte
ORDER BY
dates.dte
generate day column values in your programming language
Thanks to #The Scrum Master for nice answer here
but I also agree this shouldn't be done in database. if you think about it you actually don't need rows with 0 count.
Prepare the calendar table with a list of months and days.
To retrieve all orders from 2012-07:
select day(c.date), count(*)
from calendar c
left join orders o on c.date=o.date
where year(c.date) = 2012
and month(c.date) = 07
group by day(c.date)