Sum column values after grouping - mysql

Please I need some guide on how to sum my NewConverts column as seen in the table below.
I have 2 tables with names tbl_cmleader and tbl_cmreport. I combine the 2
tables to run this query as seen below:
SELECT mdate AS MDate, WEEK(mdate) AS MWeek, WEEK(NOW()) AS CWeek, nconvt AS
NewConverts, tbl_cmreport.cml_id, tbl_cmleader.grp_id FROM tbl_cmreport INNER JOIN
tbl_cmleader ON tbl_cmreport.mem_id = tbl_cmleader.mem_id WHERE tbl_cmleader.grp_id = 12
and mdate = '2022-07-08' ORDER BY mdate DESC
After running this query, I get the result as seen below:
MDate
MWeek
CWeek
NewConverts
cml_id
grp_id
2022-07-08
27
28
5
142
12
2022-07-08
27
28
5
142
12
2022-07-08
27
28
5
142
12
2022-07-08
27
28
1
143
12
2022-07-08
27
28
1
143
12
2022-07-08
27
28
1
143
12
2022-07-08
27
28
1
143
12
2022-07-08
27
28
1
143
12
2022-07-08
27
28
1
131
12
2022-07-08
27
28
1
131
12
2022-07-08
27
28
1
131
12
2022-07-08
27
28
1
131
12
2022-07-08
27
28
1
131
12
2022-07-08
27
28
1
132
12
2022-07-08
27
28
1
132
12
2022-07-08
27
28
1
132
12
2022-07-08
27
28
1
132
12
2022-07-08
27
28
1
132
12
However, I can't use this result to achieve what I want because the values are much. So
I add a Group By to help reduce the contents and give me the right values as seen in the query below.
SELECT mdate AS MDate, WEEK(mdate) AS MWeek, WEEK(NOW()) AS CWeek, nconvt AS
NewConverts, tbl_cmreport.cml_id, tbl_cmleader.grp_id FROM tbl_cmreport INNER JOIN
tbl_cmleader ON tbl_cmreport.mem_id = tbl_cmleader.mem_id WHERE tbl_cmleader.grp_id = 12
and mdate = '2022-07-08' GROUP BY mdate, tbl_cmleader.cml_id ORDER BY mdate DESC
At the end I get this results below
MDate
MWeek
CWeek
NewConverts
cml_id
grp_id
2022-07-08
27
28
5
142
12
2022-07-08
27
28
1
143
12
2022-07-08
27
28
1
131
12
2022-07-08
27
28
1
132
12
2022-07-08
27
28
1
134
12
This is the final table I want. Now from this table, I want to SUM the
NewConverts column to get a value of 9 but instead I am getting 36.
I run this query below to SUM the NewConverts column. The value I expect after the summation is a 9 but instead I am getting 36.
SELECT mdate AS MDate, WEEK(mdate) AS MWeek, WEEK(NOW()) AS CWeek, SUM(nconvt) AS
NewConverts, tbl_cmreport.cml_id, tbl_cmleader.grp_id FROM tbl_cmreport INNER JOIN
tbl_cmleader ON tbl_cmreport.mem_id = tbl_cmleader.mem_id WHERE tbl_cmleader.grp_id = 12
and mdate = '2022-07-08'
I am getting 36 under column NewConverts buts that's not what I want
MDate
MWeek
CWeek
NewConverts
cml_id
grp_id
2022-07-08
27
28
36
142
12
What I want is a 9 under column NewConverts as seen below
MDate
MWeek
CWeek
NewConverts
cml_id
grp_id
2022-07-08
27
28
9
142
12
Please I need help on how to rewrite the query below to get the right result
SELECT mdate AS MDate, WEEK(mdate) AS MWeek, WEEK(NOW()) AS CWeek, SUM(nconvt) AS
NewConverts, tbl_cmreport.cml_id, tbl_cmleader.grp_id FROM tbl_cmreport INNER JOIN
tbl_cmleader ON tbl_cmreport.mem_id = tbl_cmleader.mem_id WHERE tbl_cmleader.grp_id = 12
and mdate = '2022-07-08'
Thank you in advance
Michael

Your queries will fail with sql_mode=only_full_group_by enabled. It is not a good practice to disable it.
To get your desired result in the query which gives the final table that you want , you could apply an outer query doing the SUM
SELECT MDate,
MWeek,
CWeek,
SUM(NewConverts) as tot_NewConverts,
max(cml_id) as max_cml_id,
grp_id
FROM (
SELECT mdate AS MDate,
WEEK(mdate) AS MWeek,
WEEK(NOW()) AS CWeek,
NewConverts,
tbl_cmleader.cml_id,
tbl_cmleader.grp_id
FROM tbl_cmleader
WHERE tbl_cmleader.grp_id = 12
AND mdate = '2022-07-08'
GROUP BY MDate,MWeek,CWeek,cml_id,NewConverts,cml_id,grp_id
) as t1
GROUP BY MDate,MWeek,CWeek,grp_id;
Note,I used only one table so I removed the inner join clause.
max(cml_id) is just to return the max cml_id, because of sql_mode=only_full_group_by disabled that returned value was arbitrary.
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=355eb49ad446b63ee507ffe93be54440

Related

GROUP BY with MAX(date), but the date is in two separate columns

I'm trying to get the list of IDs of all the rows with latest posting date for each author in a table, for example:
id author_id date
1 12 2020-12-23
2 12 2021-01-06
3 12 2021-04-12
4 12 2021-02-10
5 17 2021-09-16
6 17 2021-05-20
7 17 2021-02-23
8 17 2021-07-02
9 24 2021-03-24
10 24 2021-02-10
11 24 2020-08-18
12 24 2020-12-14
The desired result should be:
id
3
5
9
I used this query and it works perfect:
SELECT a.id
FROM (
SELECT author_id, MAX(`date`) as MaxDate
FROM `posts_log`
GROUP BY author_id
) b
INNER JOIN `posts_log` a
ON a.author_id = b.author_id AND a.date = b.MaxDate
But let's imagine that situation changed. Now author is allowed to post only once per month. So the table changed too and 'date' column became separated:
id author_id month year
1 12 12 2020
2 12 1 2021
3 12 4 2021
4 12 2 2021
5 17 9 2021
6 17 5 2021
7 17 2 2021
8 17 7 2021
9 24 3 2021
10 24 2 2021
11 24 8 2020
12 24 12 2020
Yeah, I know, looks a little bit stupid, but this wasn't my decision. Now I have such table and I'm not allowed to change the structure.
The question is: How to get the same result with this new table. Is it possible in MySQL?
You can use similar logic. Just instead of the date, use a calculated value from year and month:
SELECT a.id
FROM (
SELECT p.author_id, MAX(p.year*100+p.month) as MaxMonth
FROM posts_log p
GROUP BY p.author_id
) b
INNER JOIN posts_log a
ON a.author_id = b.author_id AND a.year*100+a.month = b.MaxMonth;

Need to fetch a MySQL result

I have following MySQL table structure,
id product_id filter_tag_id
14 1 48
17 3 49
18 10 49
19 10 54
20 11 49
21 11 55
22 12 49
23 12 56
24 9 48
25 9 52
26 6 48
27 6 53
28 7 48
29 7 56
30 8 48
31 8 53
32 13 48
33 13 52
34 14 48
35 14 54
36 14 55
37 15 48
38 15 55
i need to fetch only those product_id's which have same filter_tag_id's,
For example only one product_id (9 and 13) having the same filter_tag_id (48 and 52), so I need to fetch only product_id 9 and 13, I'm trying following query, but no success yet.
select product_id from filter_data where filter_tag_id=52 AND filter_tag_id=48;
select product_id from filter_data where filter_tag_id in (52,48);
First query return no result and second one returning wrong results
Use self-join. It looks like more complicated than GROUP BY, but it is faster than group-by. Because with GROUP BY approach, those which only has 48 or 52 should be groupped that is not unneeded rows.
SELECT t1.product_id
FROM filter_data t1 INNER JOIN filter_data t2 ON t1.product_id = t2.product_id
WHERE t1.filter_tag_id = 48 AND t2.filter_tag_id = 52;
If what you want is to find only product_ids having filter_tag_id values equal to 48 and 52 and nothing else but these two values, then try:
SELECT product_id
FROM mytable
GROUP BY product_id
HAVING COUNT(CASE WHEN filter_tag_id = 48 THEN 1 END) > 0 AND
COUNT(CASE WHEN filter_tag_id = 52 THEN 1 END) > 0 AND
COUNT(CASE WHEN filter_tag_id NOT IN (48,52) THEN 1 END) = 0
Demo here
use GROUP BY
Select product_id,COUNT(DISTINCT filter_tag_id) filter_match
from filter_data where filter_tag_id in (52,48)
GROUP BY product_id
HAVING filter_match = 2
the value of filter_match is count you will pass in condition

Get difference between values in MySQL

I have a table with following columns
id pl_date month scores kID
1 20015/02/04 02 9 244
2 20015/02/05 02 12 244
3 20015/02/08 02 8 244
4 20015/02/22 02 24 244
5 20015/03/10 03 10 244
6 20015/03/11 03 12 244
7 20015/03/12 03 10 244
8 20015/03/13 03 12 244
My goal is to calculate the score's difference using a specific SELECT with MySQL
id pl_date month scores kID diff
1 2015/02/04 02 9 244 -3
2 2015/02/05 02 12 244 +4
3 2015/02/08 02 8 244 -16
4 2015/02/22 02 24 244 +14
5 2015/03/10 03 10 244 -2
6 2015/03/11 03 12 244 +2
7 2015/03/12 03 10 244 -2
8 2015/03/13 03 12 244 12
I tried to use the subquery as shown below, but it does not work.
SELECT b.id, (b.max_count-b.min_count) AS DIFF
FROM
(SELECT id, MAX(scores) as max_count, MIN(scores) as min_count
FROM myTable
WHERE month = 03 AND kID = 244
GROUP BY kID) b
You can join the table with itself (a self-join), but with the id shifted by one to do this:
select t1.*, ifnull(t1.scores - t2.scores, t1.scores) as diff
from table1 t1
left join table1 t2 on t1.id + 1 = t2.id
If you only want the diff to be calculated within some grouping (like kID), just add those conditions to the join.
Another approach would be to use a correlated subquery (this uses dates instead of id to determine the successor):
select
t1.*,
t1.scores
- ifnull(
(select scores
from table1
where pl_date > t1.pl_date
limit 1)
,0) as diff
from table1 t1
order by id;
Sample SQL Fiddle (both approaches)

How to find the latest survey an employee attended?

My table structure is as follows:
employee_survey_id employee_id took_survey_date visual_percent
27 10 2014-08-03 37
29 10 2012-09-11 33
30 4 2014-11-03 30
31 6 2015-03-02 37
32 10 2015-03-04 32
33 4 2015-03-04 33
34 7 2015-03-05 0
I want the list of latest survey information for each employee.
Example:
employee_survey_id Employee_id took_survey_date visual_percent
32 10 2015-03-04 32
33 4 2015-03-04 33
31 6 2015-03-02 37
34 7 2015-03-05 0
I am using mysql. Hope I have explained my question clearly.
You want the group-wise minimum, which can be found by first grouping the table and then joining the results back:
SELECT *
FROM myTable NATURAL JOIN (
SELECT employee_id, MAX(took_survey_date) took_survey_date
FROM myTable
GROUP BY employee_id
) t
See it on sqlfiddle.
Try:
SELECT * FROM employees GROUP BY Employee_id ORDER BY took_survey_date DESC

SQL Count Average

I have table like
id userid semid courseid coursename total
1 36 17 13 CA 23
2 36 17 5 CB 46
3 36 17 8 CC 20
4 36 19 16 CD 34
5 36 19 13 CA 31
6 36 19 3 CA# 29
7 36 19 7 CE 60
8 36 10 9 CK 32
9 36 10 15 CH 56
I need average of semid for a userid i.e., SUM(courseid) /count (moduleid), It was showing 9 as module count, but I have only 3 modules.
This is my query
SELECT userid, SUM(total)/count(semid) FROM custom WHERE userid=36
just use the AVG( ) function
SELECT userid, semid, AVG(total)
FROM custom
WHERE userid = 36
GROUP BY userid, semid
SQLFiddle Demo
SELECT userid, SUM(total)/count(distinct semid) FROM custom WHERE userid=36
Try this query
There is MYSQL aggregate function AVG() for finding Average . #John Totet Woo has posted the answer.