mysql Left Join, group by with count - mysql

I have two tables - one for courses and one for people attending the course.
Both are joined by course_id
table 1: firstaid - has all the course names
table 2: first_aid_att - records attendees and captures first aid
course id
I would like to get a count of attendees per course.
I have got a join working but don't know how to do the group by and count.
SELECT *
FROM firstaid
LEFT JOIN first_aid_att ON firstaid.course_id = first_aid_att.course_id
ORDER BY `sortDate` ASC

Try this:
SELECT f1.*, COUNT(f2.course_id)
FROM firstaid f1
LEFT JOIN first_aid_att f2 ON (f1.course_id = f2.course_id)
GROUP BY f1.course_id
ORDER BY f2.sortDate

Related

How do add data to multiple columns at the same time

I got this last task before I can go to bed...
Make a query that shows the name(not the id) of players who have won the lottery more than once, how many times they've won and the name(not the id) of the municipality they live in.
Players-table: PlayerNum, Name, Address, MunicipalityID
Winners-table: PlayerNum, DrawID
Municipality-table: MunicipalityID, County, Population, Name
Thank you sooo much in advance!!
You need to join the tables and do a sub query on the winner table using count and group by the join the result set with player
Not sure what the draw table does
You really should make an attempt instead of just asking for the solution.
Your starting point is to find the users who have won more than once. This is a simple GROUP BY of PlayerNum and the HAVING clause to limit the result based on the COUNT -
SELECT PlayerNum, COUNT(DrawID) AS num_wins
FROM Winners
GROUP BY PlayerNum
HAVING num_wins > 1
The next step is to add the names of the players. For this you need to join to the Players table and I have added table aliases (w & p) to avoid retyping the full table name each time -
SELECT p.Name, COUNT(DrawID) AS num_wins
FROM Winners w
INNER JOIN Players p
ON w.PlayerNum = p.PlayerNum
GROUP BY w.PlayerNum
HAVING num_wins > 1
And then finally the join to Municipality to get the Name with a column alias as we already have a Name column -
SELECT p.Name, COUNT(DrawID) AS num_wins, m.Name AS MunName
FROM Winners w
INNER JOIN Players p
ON w.PlayerNum = p.PlayerNum
INNER JOIN Municipality m
ON p.MunicipalityID = m.MunicipalityID
GROUP BY w.PlayerNum
HAVING num_wins > 1

Use SELECT through three table

I tried to write a query, but unfortunately I didn't succeed.
I want to know how many packages delivered over a given period by a person.
So I want to know how many packages were delivered by John (user_id = 1) between 01-02-18 and 28-02-18. John drives another car (another plate_id) every day.
(orders_drivers.user_id, plates.plate_name, orders.delivery_date, orders.package_amount)
I have 3 table:
orders with plate_id delivery_date package_amount
plates with plate_id plate_name
orders_drivers with plate_id plate_date user_id
I tried some solutions but didn't get the expected result. Thanks!
Try using JOINS as shown below:
SELECT SUM(o.package_amount)
FROM orders o INNER JOIN orders_drivers od
ON o.plate_id=od.plate_id
WHERE od.user_id=<the_user_id>;
See MySQL Join Made Easy for insight.
You can also use a subquery:
SELECT SUM(o.package_amount)
FROM orders o
WHERE EXISTS (SELECT 1
FROM orders_drivers od
WHERE user_id=<user_id> AND o.plate_id=od.plate_id);
SELECT sum(orders.package_amount) AS amount
FROM orders
LEFT JOIN plates ON orders.plate_id = orders_drivers.plate_id
LEFT JOIN orders_driver ON orders.plate_id = orders_drivers.plate_id
WHERE orders.delivery_date > date1 AND orders.delivery_date < date2 AND orders_driver.user_id = userid
GROUP BY orders_drivers.user_id
But seriously, you need to ask questions that makes more sense.
sum is a function to add all values that has been grouped by GROUP BY.
LEFT JOIN connects all tables by id = id. Any other join can do this in this case, as all ids are unique (at least I hope).
WHERE, where you give the dates and user.
And GROUP BY userid, so if there are more records of the same id, they are returned as one (and summed by their pack amount.)
With the AS, your result is returned under the name 'amount',
If you want the total of packageamount by user in a period, you can use this query:
UPDATE: add a where clause on user_id, to retrieve John related data
SELECT od.user_id
, p.plate_name
, SUM(o.package_amount) AS TotalPackageAmount
FROM orders_drivers od
JOIN plates p
ON o.plate_id = od.plate_id
JOIN orders o
ON o.plate_id = od.plate_id
WHERE o.delivery_date BETWEEN convert(datetime,01/02/2018,103) AND convert(datetime,28/02/2018,103)
AND od.user_id = 1
GROUP BY od.user_id
, p.plate_name
It groups rows on user_id and plate_name, filter a period of delivery_date(s) and then calculate the sum of packageamount for the group

How to join on a row with max value

I have three tables: households, voters, door_knocks
Each household can have several voters associated with it. Each household can also have several door knocks associated with it.
I'm trying to pull together all the voters in a household and the date of the last door_knock from the door_knocks table and I'm having trouble figuring out the proper query syntax. Here is my latest attempt:
SELECT households.hh_id, voters.id
FROM households
INNER JOIN voters ON households.hh_id = voters.hh_id
INNER JOIN ( SELECT MAX(dk.date), dk.hh_id FROM door_knocks dk GROUP BY dk.date) dks
ON dks.hh_id = households.hh_id
WHERE households.street = ?
The above query pulls up one result for each door knock, however. I just want the the date from the last door knock.
So, what it sounds like you're hoping for conceptually is a table that lists the last date of a knock for each houshold.
You'd like to join against that table and combine it with the voters and the households.
what your query does is give you a table of all the dates (group by dk.date) and for each date list all the households.
If you group by hh_id instead, then you will get the max date for each given household.
SELECT households.hh_id, voters.id, dks.max_date
FROM households
INNER JOIN voters ON households.hh_id = voters.hh_id
INNER JOIN ( SELECT MAX(dk.date) as max_date, dk.hh_id FROM door_knocks dk GROUP BY dk.hh_id dks
ON dks.hh_id = households.hh_id
WHERE households.street = ?

Join query for getting non matching records

I have a question regarding MySql statement. I have 2 tables, record and training. Training table contains list of all courses, and record table contains list of courses that the user have attend. Training table is below
Record table format:
I want to get list non attending courses of each user. For eg: From the above table structure, user 277 is attending 130,167,128 & 2. So the non attending courses of user 277 is 3,4,5,7,8,9,147,11,12.
How can i write sql statement for getting the above result? Please help
Its something like this
SELECT * FROM training t WHERE t.id NOT IN (select trainingId from record where UserId=277 && piId=1) && t.status=1 ORDER BY t.categoryId
select id from training where id not in ( select trainingid from record where userid = yourid)
Get a list of users, cross join that with the training courses and then LEFT OUTER JOIN that to the table of training courses done by users. Us the WHERE clause to check there wasn't a match to the last table.
Untested, but something like this:-
SELECT sub_user.UserId, t.id
FROM
(
SELECT DISTINCT UserId from record
) sub_user
CROSS JOIN Training t
LEFT OUTER JOIN Record r
ON sub_user.UserId = r.UserId
AND r.trainingId = t.id
WHERE r.id IS NULL
If you have a table of users (which you probably do) then you could eliminate the sub query and replace it with that table.

MYSQL display all records and count related records

I have 3 tables teacher subject and assignments. When a teacher logs in, I want to display all the subjects regardless if he is the teacher and regardless if there is related records or not. If there is no related records (assignments) i want it to display 0.
Teacher Table: Teacher_PK, Teacher_name
Subject Table: Subject_PK, Teacher_fk, Subject_name,
Assignments Table: Assignment_PK, Subject_fk, assignment_name
Right now i have it like this:
"SELECT *, count(a.subject_fk)
FROM assignment AS b
LEFT OUTER JOIN subject AS a
ON a.subject_fk = b.subject_PK
WHERE a.teacher_fk = $sessionVar
GROUP BY b.subject_fk
ORDER BY b.subject_name ASC";
The problem with this query is that it does not show all subjects, it only shows the subject if there are related tables.
English (3)
Math(2)
What i want it to display is
English(3)
Math(2)
Gym(0)
Science(0)
Thank you for any help.
All subjects in the Subject table
SELECT
s.*,
count(a.assignment_pk) as numAssignments
FROM
Subject s
LEFT OUTER JOIN Assignments a ON
s.Subject_pk = a.Subject_fk AND
a.teacher_fk = $sessionVar
GROUP BY
s.*
ORDER BY
s.subject_name ASC
edit - moved the filter on teacher id to the outer join section