I have the following 3 tables and i would like to know the correct sql for the expected result as below.
my sql here is not working;
select h.pid,
h.name,
sum(r.amount1) as total1,
sum(r.amount2) as total2,
count(g.pid) as times,
sum(g.take) as totaltaken
from history h
left join rpt_revenue r on h.pid=r.pid
left join guest g on g.pid=r.pid
group by h.pid, h.name;
history
pid name
1 peter
2 may
rpt_revenue
id pid amount1 amount2
1 1 10.00 11.00
2 2 20.00 20.00
3 1 2.00 2.00
4 2 2.00 2.00
guest
gid pid id take
1 1 1 2
2 1 3 2
3 2 2 3
expected result
pid total1 total2 times totaltaken
1 12.00 13.00 2 4
2 22.00 22.00 1 3
So to be able to use aggregate function over join, you should first aggregate your data in a join subquery and then aggregate all of them at the top level
here some examples of aggregation
Related
hi guys i really newbie in sql, i need help to generate percentage of attendance, here is the table:
Table Schedule
Schedule_ID Course_ID Lecture_ID Start_Date End_Date Course_Days
1 1 11 2019-09-09 2019-12-08 2,4,6
2 3 4 2019-09-09 2019-12-08 3,4
3 4 13 2019-09-09 2019-12-08 2,5
4 5 28 2019-09-09 2019-12-08 3
5 2 56 2020-01-27 2020-04-26 2,4
6 7 1 2020-01-27 2020-04-26 4,5
7 1 11 2020-01-27 2020-04-26 2,4,6
8 7 22 2020-01-27 2020-04-26 2,3
9 8 56 2020-01-27 2020-04-26 5
10 3 37 2020-01-27 2020-04-26 5,6
Reference of days of week used in this data.
1: Sunday, 2:Monday, 3:Tuesday, 4:Wednesday, 5:Thursday, 6:Friday, 7:Saturday
Table course_attendance
ID STUDENT_ID SCHEDULE_ID ATTEND_DT
1 1 2 2019-09-10
2 1 2 2019-09-11
3 1 2 2019-09-17
4 1 2 2019-09-18
......
46 2 1 2019-12-02
47 2 1 2019-09-11
48 2 1 2019-09-18
49 2 1 2019-09-25
50 2 1 2019-10-09
51 2 1 2019-10-16
....
111 6 1 2019-09-23
112 6 1 2019-09-30
113 6 1 2019-10-07
114 6 1 2019-10-14
table student
ID NAME
1 Jonny
2 Cecilia
3 Frank
4 Jones
5 Don
6 Harry
i need to show up like this :
STUDENT_ID NAME Course_ID Attendance rate
1 Jonny 1 82%
2 Cecilia 1 30%
3 Frank 3 100%
4 Jones 2 100%
5 Don 2 25%
6 Harry 4 40%
EDIT this my last step to get percentage:
result:
with main as (
select ca.STUDENT_ID,
ca.SCHEDULE_ID,
s.COURSE_ID,
co.NAME as course_name,
st.NAME,
count(ca.ID) as total_attendance,
((CHAR_LENGTH(s.COURSE_DAYS) - CHAR_LENGTH(REPLACE(s.COURSE_DAYS , ',', '')) + 1) * 13) as attendance_needed
from univ.course_attendance ca
left join univ.schedule s on ca.SCHEDULE_ID = s.ID
left join univ.student st on ca.SCHEDULE_ID = st.ID
left join univ.course co on ca.SCHEDULE_ID = co.ID
group by ca.STUDENT_ID, ca.SCHEDULE_ID
)
select *,total_attendance/attendance_needed as attendance_percentage
from main
order by 1,2;
This can be done following three steps.
Step 1: Calculate the total number of days a particular course of a schedule has. It's a good thing the start_date is always on Monday and the end_date is always on Sunday, which makes the week complete and saves some trouble. By calculating the total number of weeks a course go through and the number of days a week has for that course, we can get the total number of days a particular course of a schedule has.
Step 2:Calculate the total number of days a student for a schedule. This is done fairly easily. Note: As the majority part of the table has been skipped and the OP has yet to provide the complete data set, I could only have 14 existing rows provided.
Step 3: Calculate the percentage for the attendance using the result from the above two steps and get other required columns.
Here is the complete statement I wrote and tested in workbench:
select t2.student_id as student_id,`name`,course_id, (t2.total_attendance/t1.total_course_days)*100 as attendance_rate
from (select schedule_id,course_id,
length(replace(course_days,',',''))*(week(end_date)-week(start_date)) as total_course_days
from Schedule) t1
JOIN
(select count(attend_dt) as total_attendance,student_id,schedule_id
from course_attendance group by student_id, schedule_id) t2
ON t1.schedule_id=t2.schedule_id
JOIN
student s
ON t2.student_id=s.id;
Here is the result set ( the attendance_rate is not nice due to the abridged course_attendance table):
student_id, name, course_id, attendance_rate
2, Cecilia, 1, 15.3846
6, Harry, 1, 10.2564
1, Jonny, 3, 15.3846
Say I have a table called students
idStudent Name
1 Billy
2 Mariah
3 Chris
4 Mark
5 Sarah
and another table called tests
idTest score student_idstudent
1 50 1
2 100 1
3 90 2
4 100 3
5 45 4
is it possible to use a combination of a join and avg() to get a result like
idStudent avg_test
1 75
2 90
3 100
4 45
5 0
SELECT s.idStudent,
AVG(COALESCE(t.score, 0)) AS avg_test
FROM students s
LEFT JOIN tests t
ON s.idStudent = t.student_idStudent
GROUP BY s.idStudent
I have this table:
ID STUDENT CLASS QUESTION ANSWER TIME
1 1 1 1 c 12:30
2 1 1 1 d 12:36
3 1 1 2 a 12:38
4 2 1 1 b 11:24
5 2 1 1 c 11:26
6 2 1 3 d 11:35
7 2 3 3 b 11:24
I'm trying to write a query that does this:
For each STUDENT in a specific CLASS select the most recent ANSWER for each QUESTION.
So, choosing class "1" would return:
ID STUDENT CLASS QUESTION ANSWER TIME
2 1 1 1 d 12:36
3 1 1 2 a 12:38
5 2 1 1 c 11:26
6 2 1 3 d 11:35
I've tried various combinations of subqueries, joins, and grouping, but nothing is working. Any ideas?
You can use a sub-query to get most recent ANSWER per QUESTION, Then use this as a derived table and join back to the original table:
SELECT m.*
FROM mytable AS m
INNER JOIN (
SELECT STUDENT, QUESTION, MAX(`TIME`) AS mTime
FROM mytable
WHERE CLASS = 1
GROUP BY STUDENT, QUESTION
) AS d ON m.STUDENT = d.STUDENT AND m.QUESTION = d.QUESTION AND m.`TIME` = d.mTime
WHERE m.CLASS = 1
Demo here
I have these two tables:
Reception
id reception_date tin_lot company_id client_id quantity weight
1 2013-12-03 00:00:00 1 1 1 10 1980.00
2 2013-12-03 00:00:00 2 1 1 1 150.00
3 2013-12-13 00:00:00 3 1 2 10 4500.00
4 2013-12-13 00:00:00 4 2 5 5 2300.00
Payment
id payment_date amount reception_id
1 2013-12-03 00:00:00 500.0 1
2 2013-12-03 00:00:00 1200.0 3
The result I want to obtain is the following:
Expected result
id reception_date tin_lot client_id weight payment_made
1 2013-12-03 00:00:00 1 1 1980.00 500.0
2 2013-12-03 00:00:00 2 1 150.00 0.0
3 2013-12-13 00:00:00 3 2 4500.00 1200.0
4 2013-12-13 00:00:00 4 5 2300.00 0.0
I'm trying this query:
select rec.id
rec.reception_date,
rec.tin_lot,
rec.client_id,
rec.weight,
pay.payment_made
from liquidation.reception rec, liquidation.payment pay
where pay.recepcion_id=rec.id
But it doesn't list the receptions with no payment.
Please help me. Thanks in advance.
you need to Left Join the payment table:
from liquidation.reception rec
left join liquidation.payment pay on ( pay.recepcion_id=rec.id)
That is because you need to learn to use left outer join and proper join syntax. Just don't use a comma in a from clause any more.
Here is the query you want:
select rec.id, rec.reception_date, rec.tin_lot, rec.client_id, rec.weight,
coalesce(pay.payment_made, 0) as payment_made
from liquidation.reception rec left outer join
liquidation.payment pay
on pay.recepcion_id = rec.id;
I have a problem regarding joining tables with group_concat. Here are the details.
table_orders:
item_cd order_id descs quantity status seq_no
1 100 coca-cola 2 A 232
2 100 pizza 1 A 233
3 101 cheeseburger 5 A 234
4 102 pepsi 4 A 235
4
table_instructions:
item_cd instruction
3 more cheese
3 less vegetable
cancelled_item_table:
quantity seq_no
1 234
1 234
1 235
Now what I want to achieve is like this:
item_cd descs quantity instructions cancelled_item
1 coca-cola 2 - -
2 pizza 1 - -
3 cheeseburger 2 more cheese, less vegetable 1,1
4 pepsi 4 - 1
This is my current query:
SELECT
ord.item_cd,
ord.order_id,
ord.descs,
ord.quantity,
GROUP_CONCAT(x.quantity) as cancelled,
GROUP_CONCAT(i.instruction) as instruct
FROM table_orders ord
LEFT JOIN cancelled_item_table x ON ord.seq_no = x.seq_no
LEFT JOIN table_instructions i ON ord.item_cd = i.item_cd
WHERE ord.status = 'A'
GROUP BY ord.order_id
and here is the output:
item_cd descs quantity instructions cancelled_item
1 coca-cola 2 - 1
2 pizza 1 - 1
3 cheeseburger 2 more cheese, more cheese,
less vegetable, less vegetable 1,1,1,1
4 pepsi 4 - 1
If you notice, cheeseburger has 2 cancelled item and 2 instruction, but the output is 4, looks like it's multiplying.
Since the join with cancelled_item_table multiplies rows, you have to join to an already grouped subquery, like this:
SELECT
ord.item_cd,
ord.order_id,
ord.descs,
ord.quantity - coalesce(x.tot,0) as quantity,
GROUP_CONCAT(i.instruction) as instruct,
x.cancelled
FROM
table_orders ord LEFT JOIN table_instructions i
ON ord.item_cd = i.item_cd LEFT JOIN
(select seq_no, count(*) as tot, GROUP_CONCAT(quantity) as cancelled
from cancelled_item_table
group by seq_no) x ON ord.seq_no = x.seq_no
WHERE ord.status = 'A'
GROUP BY ord.item_cd, ord.order_id, ord.descs, quantity