mysql sum and show all registries - mysql

im trying to sum and show all registries in mysql.
i have this query:
select `deliverables`.*,
`users`.`first_name`,
`users`.`last_name`
from `deliverables`
inner join `users` on `users`.`id` = `deliverables`.`user_id`
where `deliverables`.`specialty_id` = '11' and
`deliverables`.`role_id` <> '1'
and the output is:
file_code file_name dedicated_hours
0001asder test-file.docx 4
0001as234w asdf.doc 2
jgfjh2546 test.docx 4
0001asder test-file.docx 1
0001asder test-file.docx 0
0001asder test-file.docx 0
i need sum the dedicated_hours where file_code is equal so it should looks like this:
file_code file_name dedicated_hours sum
0001asder test-file.docx 4 5
0001as234w asdf.doc 2 2
jgfjh2546 test.docx 4 4
0001asder test-file.docx 1 5
0001asder test-file.docx 0 5
0001asder test-file.docx 0 5
im using sum(dedicated_hours) and group by file_code but it only show:
file_code file_name dedicated_hours sum
0001asder test-file.docx 4 5
0001as234w asdf.doc 2 2
jgfjh2546 test.docx 4 4
How can i sum and show all registries at the same time?

Your MySQL version (5.0.12) does not support Window Functions (it should be a decent incentive enough to upgrade to get the latest goodies :)
Nevertheless, we can use a Derived Table to determine the aggregated SUM() for a file_code separately. Then, we can simply Join back to the main tables, to show the sum column.
SELECT
d.file_code,
d.file_name,
d.dedicated_hours,
dt.sum,
u.first_name,
u.last_name
FROM deliverables AS d
JOIN users AS u
ON u.id = d.user_id
JOIN
(
SELECT file_code,
SUM(dedicated_hours) AS sum
WHERE speciality_id = '11' AND
role_id <> '1'
GROUP BY file_code
) AS dt
ON dt.file_code = d.file_code
WHERE d.speciality_id = '11' AND
d.role_id <> '1'
MySQL 8.0.2 and above solution would be simply using SUM(..) OVER (..)
SELECT
d.file_code,
d.file_name,
d.dedicated_hours,
SUM(d.dedicated_hours) OVER (PARTITION BY d.file_code) AS sum,
u.first_name,
u.last_name
FROM deliverables AS d
JOIN users AS u
ON u.id = d.user_id
WHERE d.speciality_id = '11' AND
d.role_id <> '1'

Related

Transform duplicate rows in columns SQL

I have the following query:
SELECT folders.name folder, s.name `schedule`, ms.month as 'month', concat(s.start, " - ", s.end) `time`,
p.name 'profession', (select count(*) from employees where profession_id = p.id) as "count_employees"
FROM schedules s
JOIN folders ON folders.id = s.folder_id
JOIN month_schedules ms ON ms.schedule_id = s.id
LEFT JOIN schedule_professions sp ON sp.schedule_id = s.id
JOIN professions p ON p.id = sp.profession_id
WHERE s.company_id = 82 AND ms.year = 2021 AND ms.month = 2
This query returns the following table
folder
schedule
month
time
profession
count_employees
folder_a
schedule_a
2
0
profession_a
3
folder_a
schedule_a
2
0
profession_b
5
folder_a
schedule_a
2
0
profession_c
1
folder_a
schedule_b
2
0
profession_a
1
folder_a
schedule_b
2
0
profession_b
0
folder_a
schedule_b
2
0
profession_c
0
but what I want is this:
folder
schedule
month
time
profession_a
profession_b
profession_c
folder_a
schedule_a
2
0
3
5
1
folder_a
schedule_b
2
0
1
0
0
The number of professions is unknown, so has to be dynamically calculated.
I tried using GROUP_CONCAT and CONCAT, but I'm a newbie with SQL, so I didn't have any success.
SELECT
folders.name folder,
s.name `schedule`,
ms.month as 'month',
concat(s.start, " - ", s.end) `time`,
count(CASE WHEN p.name="profession_a" THEN 1 ELSE 0 END) 'profession_a',
count(CASE WHEN p.name="profession_b" THEN 1 ELSE 0 END) 'profession_b',
count(CASE WHEN p.name="profession_c" THEN 1 ELSE 0 END) 'profession_c',
(select count(*) from employees where profession_id = p.id) as "count_employees"
FROM schedules s
JOIN folders ON folders.id = s.folder_id
JOIN month_schedules ms ON ms.schedule_id = s.id
LEFT JOIN schedule_professions sp ON sp.schedule_id = s.id
JOIN professions p ON p.id = sp.profession_id
WHERE s.company_id = 82 AND ms.year = 2021 AND ms.month = 2
You only need to check if the GROUP BY is correct, i did not do that check.... 😉

MySQL combining multiple rows into one row

I've two tables as below:
1. tbl_student:
id name
1 raj
2 raja
3 raju
4 rajan
tbl_attendance
id student_id month attended_days
1 1 1 6
2 1 2 16
3 8 1 8
4 7 2 14
5 8 2 13
6 7 1 11
I need to join these two tables combining multiple rows for each month for each student from tbl_attendance into a single row to obtain a result like this:
id name month attended_days month attended_days
1 raj 1 6 2 16
7 raja 1 11 2 14
8 rajan 1 8 2 13
Thanks in advance for any help.
Instead of displaying month value in each of the records,
you can use them as column headers and attendance as their value.
Use pivot type solution to achieve required solution.
Example:
select s.id as student_id
, s.name as student_name
, max( case when a.month = 1 then a.attended_days else null end ) as month_1
, max( case when a.month = 2 then a.attended_days else null end ) as month_2
, max( case when a.month = 3 then a.attended_days else null end ) as month_3
-- ...
, max( case when a.month = 12 then a.attended_days else null end ) as month_12
from table_student s
left join table_attendance a on s.id = a.student_id
group by s.id, s.name
Your question is not very complete, but i think you want something like this:
select s.*,
coalesce(a1.month, a2.month, a3.month) as month,
coalesce(a1.attended_days , a2.attended_days , a3.attended_days ) as attended_days
from table_student s
left join table_attendance a1 on s.id = a1.student_id and a1.month = 1
left join table_attendance a2 on s.id = a2.student_id and a2.month = 2
left join table_attendance a3 on s.id = a3.student_id and a3.month = 3
The previous code is used if you want to show all months in one column. For multiple columns, you can use this example:
select s.*,
a1.month as month_1,
a2.month as month_2,
a3.month as month_3,
a1.attended_days as attended_days_1,
a2.attended_days as attended_days_2,
a3.attended_days as attended_days_3
from table_student s
left join table_attendance a1 on s.id = a1.student_id and a1.month = 1
left join table_attendance a2 on s.id = a2.student_id and a2.month = 2
left join table_attendance a3 on s.id = a3.student_id and a3.month = 3
Do this for all the 12 months. I used 3 as example.

SQL Group Function

I was trying to get count of three columns by using SUM(), when I execute the query, it says '#1111 - Invalid use of group function'. I tried correcting the group functions, even though it shows the error.
I need the perfect count of columns 2,3,4
SELECT c.name,
SUM(CASE WHEN COUNT(distinct cmc.id) = COUNT(distinct ccc.id) THEN 1 ELSE 0 END) AS "COND1",
SUM(CASE WHEN COUNT(distinct cmc.id) > 0 AND COUNT(distinct cmc.id) != COUNT(distinct ccc.id) THEN 2 ELSE 0 END) AS "COND2",
SUM(CASE WHEN COUNT(distinct cmc.id) = 0 THEN 3 ELSE 0 END) AS "COND3"
FROM
lesson_modules_completion cmc
INNER JOIN lesson_modules cm ON cmc.lessonmoduleid = cm.id
INNER JOIN lesson_completion_settings ccc ON cm.lesson = ccc.lesson
INNER JOIN lesson c ON cm.lesson = c.id
INNER JOIN user u ON u.id = cmc.userid
WHERE ccc.criteriatype=4
GROUP BY c.name
I need the count of each user has Completed modules, Inprocess modules and Notstarted modules for each course, where getting the count of userids from table CC by taking courseia from table CM, get number of modules that an user has completed from each course.
(A course can have morethan one module and a course can have number of users attempted all modules, few modules or not attempted at all).
So, I need number of users - has done number of modules - in a course. (3 logics)
(COND1 i.e.,Completed.Users ) : If number of modules attempted is equal to number of modinstance from table CMS (ex: no. of modules attempted by a user per course= 9, no.modinstance = 9. Because 7 is not equal to 9, They are completed.)
(COND2 i.e.,Inprocess.Users ) : Number of modules attempted should be >0, but not equal to [count(modinstance) per course] (ex: no. of modules attempted by a user per course= 7 , no.modinstance = 9. Because 7 is not equal to 9, They are Inprocess.)
(COND2 i.e.,Nostart.Users ) : Number of modules attempted should be equal to 0, (ex: no. of modules attempted by a user per course= 0. They are Notstarted).
You can refer my query, It was all doing good, but I need the count of COND1, COND2, COND3
I need the OUTPUT :
lesson COND1 COND2 COND3
5 65 32 6
6 40 12 15
8 43 56 0
9 0 7 9
select lesson,sum(COND1) as COND1, sum(COND2) as COND2,sum(COND3) as COND3
from
(
SELECT c.name,
ccc.lesson,
CASE WHEN COUNT(distinct cmc.id) = COUNT(distinct ccc.id) THEN 1 ELSE 0 END AS "COND1",
CASE WHEN COUNT(distinct cmc.id) > 0 AND COUNT(distinct cmc.id) != COUNT(distinct ccc.id) THEN 2 ELSE 0 END AS "COND2",
CASE WHEN COUNT(distinct cmc.id) = 0 THEN 3 ELSE 0 END AS "COND3"
FROM
lesson_modules_completion cmc
INNER JOIN lesson_modules cm ON cmc.lessonmoduleid = cm.id
INNER JOIN lesson_completion_settings ccc ON cm.lesson = ccc.lesson
INNER JOIN lesson c ON cm.lesson = c.id
INNER JOIN user u ON u.id = cmc.userid
WHERE ccc.criteriatype=4
GROUP BY c.name,ccc.lesson
) t
group by lesson

mysql query output the number of people that have purchased any of the same models that the user has purchased

purchased_models
user_id model_id
1 1
1 4
1 9
1 3
2 3
2 2
2 7
2 4
3 9
3 6
3 1
3 5
4 8
4 7
4 9
4 1
5 8
5 9
Using the above table, write a query to output a table the columns of which are user_id, number of models that user has purchased, and the number of people that have purchased any of the same models that the user in question has purchased. The result should look like this:
Result
user_id models_purchased users_purchasing_same_models
1 4 4
2 4 2
3 4 3
4 4 4
5 2 3
Got the first two with:
SELECT
DISTINCT user_id,
COUNT(DISTINCT model_id)
FROM
purchased_models
GROUP BY user_id
, but having trouble with the third one. Any help would be greatly appreciated. Thanks!
One way to do this is to use a correlated subquery that counts the distinct number of users that has purchased any of the models that the user referenced in the outer scope has purchased:
select
t1.user_id,
count(distinct t1.model_id) models_purchased,
(
select count(distinct user_id)
from purchased_models t2
where t2.model_id in (
select model_id
from purchased_models
where user_id = t1.user_id
and t2.user_id <> t1.user_id
)
) users_purchasing_same_models
from purchased_models t1
group by t1.user_id
order by t1.user_id
I would personaly try to self-join the table and conditional sum, as follows:
SELECT
a.user_id AS Id,
SUM(CASE WHEN a.user_id = b.user_id AND a.model_id=b.model_id THEN 1 ELSE 0 END) AS ModelCount,
SUM(CASE WHEN a.user_id != b.user_id AND a.model_id=b.model_id THEN 1 ELSE 0 END) AS Others
FROM purchased_models AS a
LEFT OUTER JOIN purchased_models AS b
ON TRUE
GROUP BY a.user_id

MySQL select using row counts and grouping

I have 2 tables, orders and order_lineitems.
orders contains the order status info (sold date, invoice no, type of sale, etc)
order_lineitems contains the item(s) for each order in a one to many relationship.
Since we provide shipping info by line item, ship_date is in the order_lineitems table, null if not shipped, a date if it is shipped.
I am trying to pull the orders where all items have shipped by comparing the number of line item rows against the line item rows that have a ship date. While I have successfully pulled all that info, I am unable to make the last step, limiting the result set to include only the completely shipped orders (number of rows = number of rows where ship_date is not null).
I know I am missing something simple, but just don't see it..
select sum(custom.lineitems) as totalitems, sum(custom.shipped) as totalshipped,
custom.invoice, z.shipregion
from (
select a.invoice, count(a.invoice) as lineitems, 0 as shipped
from order_lineitem a
group by a.invoice
UNION ALL
select b.invoice, 0 as notshipped, count(b.ship_date) as shipped
from order_lineitem b
where b.ship_date is not null
group by b.invoice
) as custom
left join orders z on custom.invoice = z.invoice
where z.result = 0
and z.respmsg like 'Approved%'
and z.shipregion <> 'PENDING'
and z.cancelorder = 0
group by custom.invoice;
This returns a result set like so (one row for each invoice in the DB)
totalitems totalshipped invoice shipregion
4 2 1000 REGION08
1 1 10001 REGION07
1 1 10004 REGION05
3 1 10006 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
What I am looking for is a result set like this - only where totalitems = totalshipped
totalitems totalshipped invoice shipregion
1 1 10001 REGION07
1 1 10004 REGION05
2 2 10007 REGION04
1 1 10008 REGION08
7 7 10009 REGION01
1 1 1001 REGION08
Use HAVING clause
SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice HAVING lineitems = shipped
OR
SELECT a.invoice, a.shipregion, a.lineitems, a.shipped
FROM (SELECT a.invoice, z.shipregion, COUNT(a.invoice) AS lineitems,
SUM(CASE WHEN a.ship_date IS NOT NULL THEN 1 ELSE 0 END) AS shipped
FROM order_lineitem a
LEFT JOIN orders z ON a.invoice = z.invoice AND z.result = 0 AND z.cancelorder = 0 AND
z.respmsg LIKE 'Approved%' AND z.shipregion <> 'PENDING'
GROUP BY a.invoice
) AS a WHERE a.lineitems = a.shipped
One more outer query needed.
select * from
(
\\Your whole query here
) as Result
where Result.totalitems = Result.totalshipped