Include zero in COUNT with GROUP BY in MySQL - mysql

I'm looking to make a query in MySQL to list all the faculties and their number of students given the following table structure:
My query looks like:
SELECT `f`.`id`, `f`.`name`, COUNT(*) `total`
FROM `student` `s`
INNER JOIN `course` `c` ON `c`.`id` = `s`.`course_id`
LEFT JOIN `faculty` `f` ON `f`.`id` = `c`.`faculty_id`
GROUP BY `c`.`faculty_id`
ORDER BY `f`.`name`
And I'm getting this result:
but I need to get all the faculties, even the ones without registered students.
If I use a LEFT JOIN with the course table I get the same results.

If you want all the faculties; your starting table for the JOIN should be the faculty table. Then do Left joins on the other table accordingly.
Use the following query:
SELECT `f`.`id`, `f`.`name`, COUNT(`s`.`id`) AS `total`
FROM `faculty` AS `f`
LEFT JOIN `course` AS `c` ON `f`.`id` = `c`.`faculty_id`
LEFT JOIN `student` AS `s` ON `c`.`id` = `s`.`course_id`
GROUP BY `f`.`id`, `f`.`name`
ORDER BY `f`.`name`

You need to revese the query, your primary tables is faculties (or use right join) :
important - since you want to count cases of zero students you need to treat NULL values that might come up, joining the students table:
SELECT
`f`.`id`, `f`.`name`, SUM(IF(s.id IS NULL, 0,1) `total`
FROM
faculty f
LEFT JOIN course c ON `f`.`id` = `c`.`faculty_id`
LEFT JOIN student s ON `c`.`id` = `s`.`course_id`
GROUP BY `c`.`faculty_id` ORDER BY `f`.`name`

Related

SQL not working when I choose some fields from the 1st table

I just used this code, and working properly with me:
SELECT
* FROM `order` as o
LEFT JOIN `services` as s ON s.`id` = o.`service_id`
LEFT JOIN `users` as u ON u.`id` = o.`users_id`
LEFT JOIN `files` as f ON f.`order_id` = o.`id`
but when I try to choose some fields from the 1st table, the results not showing the other tables
SELECT
o.`id` AS `id`,
o.`service_id`,
o.`extras`,
o.`quantity`,
o.`price`,
o.`links`,
o.`keywords`,
o.`status_id`,
o.`users_id`,
o.`date`,
o.`notes`,
o.`c_reason`,
o.`agent_star`
FROM `order` as o
LEFT JOIN `services` as s ON s.`id` = o.`service_id`
LEFT JOIN `users` as u ON u.`id` = o.`users_id`
LEFT JOIN `files` as f ON f.`order_id` = o.`id`
I don't know what is the exact error on the 2nd code, I need to show all columns from the tables: services, users & files
all columns or just defined columns
You when you select * from a join you are selecting all results from all tables involved.
When you are specifying orders you are only getting the results as they pertain to the orders table you get the same thing if you were to do SELECT o.* so if you want to see shared fields from different tables you have to specify them in your select statement as well.
Basically you're seeing the Different between SELECT * and SELECT o.*
This code is working for me, thanks everybody :)
SELECT
o.`id` AS `id`,
o.`service_id`,
o.`extras`,
o.`quantity`,
o.`price`,
o.`links`,
o.`keywords`,
o.`status_id`,
o.`users_id`,
o.`date`,
o.`notes`,
o.`c_reason`,
o.`agent_star`
s.*
u.*
f.*
FROM `order` as o
LEFT JOIN `services` as s ON s.`id` = o.`service_id`
LEFT JOIN `users` as u ON u.`id` = o.`users_id`
LEFT JOIN `files` as f ON f.`order_id` = o.`id`

MYSQL GROUP BY - slow query

I have a query like below, please help to give proper index for this, the contact table have more than 20K records and it take nearly 20 secs to load.
Hope the group by clause makes the problem, if I remove the group by clause total record is more than 300k.
SELECT `a`.*, CONCAT(a.`firstname`, " ", a.`lastname`) AS `cont_name`, CONCAT(a.`position`, " / ", a.`company`) AS `comp_pos`, `e`.`name` AS `industry_name`, CONCAT(f.`firstname`, " ", f.`lastname`) AS `created_by`
FROM `contacts` AS `a`
LEFT JOIN `user_centres` AS `b` ON a.user_id = b.user_id
LEFT JOIN `group_contacts` AS `c` ON a.id = c.contact_id
LEFT JOIN `groups` AS `d` ON c.group_id = d.id
LEFT JOIN `industries` AS `e` ON e.id = a.industry_id
LEFT JOIN `users` AS `f` ON f.id = a.user_id
WHERE (1)
GROUP BY `a`.`id`
ORDER BY `a`.`created` desc
Explain shows like this - 20145 Using temporary; Using filesort
You can try these steps
There is no use of table group ( d ), so you can remove left join to group from this query
Add index for user_id, contact_id and industry_id ( I hope these ids are joining table primary_keys ) in contacts table
check these ids user_id, contact_id and industry_id types ( INT ) are same.

MySQL query not working - can't figure out why

I have this query that I'm pretty sure it set up correctly, but it keeps returning no results, when I know there is 1 row that should be returned.
SELECT
`t1`.id,
`t1`.length,
`t2`.last,
`t2`.first,
`t4`.name,
`t5`.text
FROM `res` AS `t1`
INNER JOIN `pt` AS `t2`
ON `t1`.ptid=`t2`.pt
INNER JOIN `docs` AS `t3`
ON `t1`.doc=`t3`.did
LEFT JOIN `user` AS `t4`
ON `t3`.user=`t4`.id
INNER JOIN `desc` AS `t5`
ON `t1`.desc=`t5`.id
ORDER BY
`t1`.date ASC
Again, not getting an error - just getting no results.
Thanks
desc is a reserved word. You need to put backticks around it.
JOIN `desc` as `t5` ON `t1`.desc=`t5`.id
should be
JOIN `desc` as `t5` ON `t1`.`desc`=`t5`.id

Joining over 4 tables

Here's a fiddle with the schema and a sample query: http://sqlfiddle.com/#!2/573ec4/9
I'm looking to return C.price using I.section and L.level, which are obtained via other joins. When using an inner join with Cost I am left with no result: http://sqlfiddle.com/#!2/573ec4/2
Since cost is a table that maps a section and level to a price, I would like to be able to calculate the price of all the showings in my query
When you are joining to the Cost table you do not include the proper join conditions:
INNER JOIN `cost` `C`
ON `I`.`Section` = c.section -- = c.section is missing
AND `L`.`level` = c.level; -- = c.level is missing
So your full query will be:
SELECT `F`.`date`,
`F`.`time`,
`F`.`tname`,
`I`.`section`,
`L`.`level`,
c.price
FROM `booking_for_schedule` `F`
INNER JOIN `booking_in_seats` `I`
on `F`.`tname`=`I`.`tname`
AND `F`.`booking_num` = `I`.`booking_num`
INNER JOIN `level` `L`
on `F`.`date`=`L`.`date`
AND `F`.`time`=`L`.`time`
AND `F`.`tname`=`L`.`tname`
INNER JOIN `cost` `C`
ON `I`.`Section` = c.section
AND `L`.`level` = c.level;
See SQL Fiddle with Demo
Looks like you're missing some clause on the INNER JOIN cost C (when you are joining on the Cost table).
It should look like this:
INNER JOIN `cost` `C` ON `I`.`Section`=`C`.`Section` AND `L`.`level`=`C`.`level`
instead of:
INNER JOIN `cost` `C` ON `I`.`Section` AND `L`.`level`
You have missed to join the columns. the reason why you have no result is because I.Section AND L.level will always return false.
SELECT F.date,
F.time,
F.tname,
I.section,
L.level,
c.*
FROM booking_for_schedule F
INNER JOIN booking_in_seats I
ON F.tname = I.tname AND
F.booking_num = I.booking_num
INNER JOIN level L
ON F.date = L.date AND
F.time = L.time AND
F.tname = L.tname
INNER JOIN cost C
ON I.Section = C.Section AND -- <<== HERE
L.level = C.level -- <<== HERE
SQLFiddle Demo
Your last line is the problem:
INNER JOIN `cost` `C` ON `I`.`Section` AND `L`.`level`
It should be this:
INNER JOIN `cost` `C` ON `I`.`Section` = `C`.`Section` AND `L`.`level` = `C`.`Level`

MySQL Query Output

I am trying to run this query however it's only outputting results of categories that have items in them, rather than all the categories. This is my query:
SELECT categories.`id` as `cat_id`, categories.`title` as `cat_title`, COUNT(tutorials.`id`) as `total`
FROM `tutorial_categories` as `categories`, `tutorials`
WHERE tutorials.`category` = categories.id
GROUP BY `cat_id`
Can anyone lead me in the right direction here? Thanks.
SELECT
categories.id ,
categories.title,
COUNT(*) as total
FROM tutorial_categories as categories
LEFT JOIN tutorials
on tutorials.category = categories.id
GROUP BY categories.id
You need to use a LEFT JOIN. Your implicit join syntax produces an inner join insetad:
SELECT
categories.`id` as `cat_id`,
categories.`title` as `cat_title`,
COUNT(tutorials.`id`) as `total`
FROM
`tutorial_categories` `categories` LEFT JOIN `tutorials` ON categories.id = tutorials.category
GROUP BY `cat_id`
You are looking for an outer join as described here : "An outer join does not require each record in the two joined tables to have a matching record"
You need to restyle the query using an outer join, instead of using the WHERE
Something like this
SELECT categories.`id` as `cat_id`, categories.`title` as `cat_title`, COUNT(tutorials.`id`) as `total`
FROM `tutorial_categories` as `categories`, `tutorials`
LEFT OUTER JOIN tutorials.`category` = categories.id
GROUP BY `cat_id`
You have a WHERE tutorials.category= categories.id set so it would only return the rows that meet that criteria. Remove that and it should return "all the categories".
SELECT categories.`id` as `cat_id`, categories.`title` as `cat_title`, COUNT(tutorials.`id`) as `total`
FROM `tutorial_categories` as `categories`, `tutorials`
GROUP BY `cat_id`