Get the each count of data by combining two tables in MySQL - mysql

I want to get the each count of data by combining two tables in MySQL. This is the scenario I have following tables. emp_tab(name, dept_id ) and dept_tab(dept_id, dept_name). I want to write a query to show the number of employees in each department with the department name.
tried code:
SELECT dept_tab.dept_name, number
FROM emp_tab
INNER JOIN dept_tab ON emp_tab.dept_id=dept_tab.dept_id;
My try is not successful. Can you please show me how can I solve this. I am beginner to MySQL

Two things:
You need to use a group by and count function
Your join was joining an invalid table
SELECT dept_tab.dept_name, COUNT(*) as number
FROM emp_tab
INNER JOIN dept_tab ON emp_tab.dept_id=dept_tab.dept_id
GROUP BY dept_tab.dept_name

You can use JOIN and GROUP BY by dept_name to count number of employees.
In your question, what is Customerstable? I assume that is dept_tab?
SELECT
d.dept_name,
COUNT(d.id) AS cnt
FROM
dept_tab d
LEFT JOIN empt_tab e
ON e.dept_id = d.dept_id
GROUP BY d.dept_name ;

Related

Having trouble a query and specifically with joins

The code below is completely wrong and does not work at all. Im basically trying to look through my tables and compile a list of DeptName and the total student number for a department where a department has more than 40 students.
Im confused about joins in general and if someone could explain and show where im going wrong. im sure there is also other problems so any help with them would help
So basically one department is connected to one module, and a student is enrolled in a module. A student cannot take a module outside of their department. So each student should have one module that connects to one department
All of the ID fields in other tables are foreign keys as you can guess and changing the tables is not what I want to do here I just want to do this query as this stands
Relevant tables columns
Table Department DeptID, DeptName, Faculty, Address
Table Modules ModuleID, ModuleName, DeptID, Programme
Table Students StudentID,StudentName,DoB,Address,StudyType,`
Table Enrolments EID,StudentID,ModuleID,Semester,Year
SELECT Department.DeptName, COUNT(Student.StudentID) AS 'No of Students' FROM Department LEFT JOIN Module ON Department.DeptID= Module.DeptID LEFT JOIN Enrolment ON Module.ModuleID= Enrolment.StudentID LEFT JOIN Student.StudentID
GROUP BY(Department.DeptID)
HAVING COUNT(Student.StudentID)>=40
I have not included every table here as there are quite a lot.
But unless i've got this completely wrong you don't need to access a ModuleID in a staff table for the module they teach or something not relevant to this at all. As no student or Dept details are in there.
If that is the case i will fix it very quickly.
SELECT Department.DeptName, COUNT(Student.StudentID) AS 'No of Students'
FROM Department
LEFT JOIN Module
ON Department.DeptID= Module.DeptID
LEFT JOIN Enrolment
-- problem #1:
ON Module.ModuleID= Enrolment.StudentID
-- problem #2:
LEFT JOIN Student.StudentID
-- problem #3:
GROUP BY(Department.DeptID)
HAVING COUNT(Student.StudentID)>=40
You're joining these two tables using the wrong field. Generally when the modeling is done correctly, you should use USING instead of ON for joins
The right side of any JOIN operator has to be a table, not a column.
You have to group by every column in the select clause that is not part of an aggregate function like COUNT. I recommend that you select the DeptID instead of the name, then use the result of this query to look up the name in a subsequent select.
Note : Following code is untested.
WITH bigDepts AS (
SELECT DeptId, COUNT(StudentID) AS StudentCount
FROM Department
JOIN Module
USING ( DeptID )
JOIN Enrolment
USING ( ModuleID )
JOIN Student
USING ( StudentID )
GROUP BY DeptID
HAVING COUNT(StudentID)>=40
)
SELECT DeptID, DeptName, StudentCount
FROM Department
JOIN bigDepts
USING ( DeptID )
Instead of left join you need to use inner join since you need to select related rows only from those three tables.
Groupy by and having clause seems fine. Since you need departments with more than 40 students instead of >= please use COUNT(e.StudentID)>40
SELECT d.DeptName, COUNT(e.StudentID) AS 'No of Students' FROM Department d INNER JOIN Module m ON d.DeptID= m.DeptID inner JOIN Enrolment e ON m.ModuleID= e.StudentID LEFT JOIN Student.StudentID
GROUP BY(d.DeptName)
HAVING COUNT(e.StudentID)>40
So your join clause was a bit iffy to students as you wrote it, and presumably these should all be inner joins.
I've reformatted your query using aliases to make it easier to read.
Since you're counting the number of rows per DeptName you can simply do count(*), likewise in your having you are after counts greater than 40 only. Without seeing your schemas and data it's not possible to know if you might have duplicate Students, if that's the case and you want distinct students count can amend to count(distinct s.studentId)
select d.DeptName, Count(*) as 'No of Students'
from Department d
join Module m on m.DeptId=d.DeptId
join Enrolment e on e.StudentId=m.ModuleId
join Students s on s.StudentId=e.studentId
group by(d.DeptName)
having Count(*)>40
Also, looking at your join conditions, is the Enrolement table relevant?
select d.DeptName, Count(*) as 'No of Students'
from Department d
join Module m on m.DeptId=d.DeptId
join Students s on s.StudentId=m.moduleId
group by(d.DeptName)
having Count(*)>40

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

Selecting count(column) from different table

I have three tables area,vehicle and employee.
ward_no is the foreign key for vehicle and employee.
I want to select the number of vehicles and number of employees and display them along with other details of area.
The query i used is:
select a.* ,count(v.vid) as vehicles,count(e.eid) as employees from area a,vehicle v,employee e where v.ward_no=a.ward_no and e.ward_no=a.ward_no group by a.name;
But the output is not what I want. I get the same values in both the columns where the count is use instead of displaying the total number of vehicles/employees in that particular area.
I'm new to MySQl
The default behavior of count is to count the non-null values.
In your case, this counts repetitions of the value.
Try adding DISTINCT inside the count:
select a.* ,count(DISTINCT v.vid) as vehicles,count(DISTINCT e.eid) as employees
from area a,vehicle v,employee e
where v.ward_no=a.ward_no and e.ward_no=a.ward_no group by a.name;
Also, it's better to use explicit JOIN rather than implicit, like this:
select a.* ,count(DISTINCT v.vid) as vehicles,count(DISTINCT e.eid) as employees
from area a JOIN vehicle v ON v.ward_no=a.ward_no
JOIN employee e ON e.ward_no=a.ward_no
group by a.name;
There may be a chance that you are getting same vehicle and employee multiple times due to the joins, Use DISTINCT in COUNT() get count of unique vehicles and employees
SELECT
a.*,
COUNT(DISTINCT v.vid) AS vehicles,
COUNT(DISTINCT e.eid) AS employees
FROM
`area` a
JOIN vehicle v
ON v.ward_no = a.ward_no
JOIN employee e
ON e.ward_no = a.ward_no
GROUP BY a.name

MySQL query issue

This is my query:
SELECT count(*) as total, dp.name,dp.id,dp.description, dp.avatar
FROM `doctors` d
right join departments dp on d.department_id = dp.id
group by d.department_id
I have to tables: doctors and departments. I want to extract the total number of doctors from each department. This query works fine, it returns me all of the deparments, which have a doctors, but not which does not have. Somehow I want to show all of the departements and a total, which represents the doctors whose belong to a department. How can i do that ?
This is the doctor table:
and this is the departments table
You can give this a try:
SELECT
(SELECT count(*) FROM doctors d WHERE d.department_id = dp.id) AS total,
dp.*
FROM departments AS dp
And if you want to use JOIN then try this:
SELECT
COUNT(d.department_id) AS total,
dp.*
FROM departments AS dp
LEFT JOIN doctors AS d ON dp.id = d.department_id
GROUP BY dp.id
SELECT (SELECT count(*) FROM doctors AS d WHERE d.id = dp.id) as total, dp.name,dp.id,dp.description, dp.avatar
FROM departments dp
there are multiple ways of doing this ofcourse, I would do it like this
i dont think you need to join you just need a count of all the doctors and you dont do anything with the rest of the information
In my couple of decades working with SQL I've never used right joins. I've always found the LEFT join easier to read. I also try and return the columns in order of the highest to lowest level of detail and finish with sum's and counts. It reads a lot better.
Try this:
SELECT dp.id,dp.name,dp.description, dp.avatar,count(*) as total
FROM departments dp
LEFT JOIN doctors d
on d.department_id = dp.id
GROUP BY dp.id,dp.name,dp.description, dp.avatar
You must always group by every column within your select clause except those that are an aggregation (e.g. sum,count) or a constant.

Select data from one table which is connected to another 2 tables

I have 3 tables: Emplyees, Jobs and Departments
What I'm trying to achieve is to get the number of emplyees from one department.
I tried something:
SELECT count(Emplyees.id) FROM Emplyees
INNER JOIN Job ON (Job.id = Emplyees.job_id)
INNER JOIN Department ON (Department.id = 2)
but it returns the number of emplyees from all departments.
Any advice please?
An EXISTS clause will allow you to limit by the existence of something without having to worry about whether or not an employee also has other jobs, which will keep your count easy to figure.
Also, since the only thing you need from the department is the id, you can leave that table out and just filter by the dept_id field of the Job table.
SELECT count(id)
FROM Employees
WHERE EXISTS (
SELECT 1
FROM Job
WHERE id = Employees.job_id
AND dept_id = 2
)
Use WHERE clause to filter out department,where clause will apply for the whole result set returned by joins,while condition in on clause will filter result from joined table only
SELECT count(e.id)
FROM Emplyees e
INNER JOIN Job j ON (j.id = e.job_id)
INNER JOIN Department d ON (j.dept_id =d.id )
WHERE d.id = 2
And also use DISTINCT in count so if any employee has applied on multiple jobs that belong to same department will be counted as 1 i.e COUNT(DISTINCT e.id)