database sql join question - sql

i have 2 tables called
Location (id, name)
Person (id, name, location_id)
A person has a location Id which joins these tables . . i would like a SQL query that gives me each location and the count of person table for that id.
i could do something like this and then add up the records in code but i want to find out a way that i only get one row per region with count of people in that region
SELECT l.*, r.id from Location l
inner join Person r
on r.location_id = l.id
order by l.name asc

You want to use aggregates and the GROUP BY clause
SELECT l.id, l.name, count(r.id)
FROM Location l
INNER JOIN Person r on r.location_id = l.id
GROUP BY l.id., l.name
ORDER BY l.name asc

Try:
Select L.Name, Count(*) PersonsCount
From Location L
Join Person P On P.Location_Id = L.Id
Group By L.Name
or if you want to see Locations with zero counts,
Select L.Name, Count(*) PersonsCount
From Location L
Left Join Person P On P.Location_Id = L.Id
Group By L.Name

SELECT lo.name, COUNT(*)
FROM LOCATION lo
JOIN PERSON p ON p.location_id = lo.id
GROUP BY lo.name
ORDER BY lo.name

try this
select count(*), Location.name, Location.id from Location, Person where Person.location_id = Location.id group by Location.id

Related

Oracle SQL - For the same two column values how many different third column

SELECT *
FROM Client cl, Contact c, Location l
WHERE l.locID = c.locID
AND cl.clientID = l.clientID
I want to find for same (locID and clientID) how many different c.contactID are out there?
You can use GROUP BY and COUNT(DISTINCT)
SELECT
l locID,
l.clientID,
COUNT( DISTINCT c.contactID)
FROM Client cl
JOIN Location l
ON cl.clientID = l.clientID
JOIN Contact c
ON l.locID = c.locID
GROUP BY
l.locID,
l.clientID;
As we are not using the client table we can remove it. The query might run faster. (The optimiser might detect that it is not used and not query it anyway)
SELECT
l locID,
l.clientID,
COUNT( DISTINCT c.contactID)
FROM
Location l
JOIN Contact c
ON l.locID = c.locID
GROUP BY
l.locID,
l.clientID;
Following the further request in the comments for for number of duplicates of [ loc id, client id, contact id ] we simply need to add contactID to the group by and put COUNT(*) instead of COUNT( DISTINCT c.contactID).
The query therefore becomes.
SELECT
l locID,
l.clientID,
c.contactID,
COUNT( * )
FROM
Location l
JOIN Contact c
ON l.locID = c.locID
GROUP BY
l.locID,
l.clientID,
c.contactID;

SQL: INNER JOIN for two levels of aggregation

My question is about a SQL query that returns a course list (see image).
Instead of the class_id, I would like to print the name of the class. The class name is stored in table classes. I already tried it with INNER JOIN, but unfortunately I haven't found a solution yet.
select
group_concat(ids) as ids,
group_concat(class_id) as class_ids,
teacher, name, weekday_hours
from
(select
l.class_id, l.teacher_id, l.name,
group_concat(l.weekday, ':', l.hour order by l.weekday, l.hour) as weekday_hours,
group_concat(l.id order by l.id) as ids
from
lessons l
group by
l.class_id, l.teacher_id, l.name) l
group by
teacher, name, weekday_hours;
You want to join in the subquery and then process the name just as you would the class_id:
select group_concat(ids) as ids,
group_concat(class_name) as class_names,
teacher, name, weekday_hours
from (select l.class_id, c.name as class_name,
l.teacher_id, l.name,
group_concat(l.weekday, ':', l.hour order by l.weekday, l.hour) as weekday_hours,
group_concat(l.id order by l.id) as ids
from lessons l join
classes c
on l.class_id = c.id
group by l.class_id, c.name, l.teacher_id, l.name
) l
group by teacher, name, weekday_hours;

How do I select how many pantients every doctor has?

I have a table of Visits on the Hospital, included DoctorID, PacientID, Date....
I did like this but I recieved an error.
SELECT
d.DoctorID, COUNT(v.DoctorID)
FROM Visits v
left join Doctors d on v.DoctorID=d.DoctorID
You care missing the group by:
SELECT d.DoctorID, COUNT(v.DoctorID)
FROM Doctors d LEFT JOIN
Visits v
ON v.DoctorID = d.DoctorID
GROUP BY d.DoctorID;
In addition, you presumably want the LEFT JOIN starting with Doctors so you keep all doctors.
Your query is missing a GROUP BY clause. Also I do not see the need for a JOIN. If you want the count of (distinct) patientsIDs per doctorID, you can get that information directly from the visit table, like so:
select doctorID, count(distinct patientID) from visits group by doctorID
Or, if you also want to see doctors that have no patients:
select d.doctorID, count(distinct v.patientID)
from doctors d
left join visits v on v.doctorID = d.doctorID
group by d.doctorID
Live demo on db<>fiddle
You are missing GroupBy clause.
So you can fix it in this way
SELECT d.Name, COUNT(v.DoctorID) AS PantientCount
FROM Doctors d
LEFT JOIN Visits v ON d.DoctorId = v.DoctorId
GROUP BY d.Name
You can also using Conditional aggregation query with a group by like below.
SELECT d.Name, SUM(CASE WHEN v.CustomerId IS NOT NULL THEN 1 ELSE 0 END) AS PantientCount
FROM Doctors d
LEFT JOIN Visits v ON d.DoctorId = v.DoctorId
GROUP BY d.Name
Output

Remove duplicate rows from answer of below query

**List all directors who directed 5000 movies or more, in descending order of the number of movies they directed
The use of Distinct before d.name doesnot help.
result = pd.read_sql_query("SELECT d.name,count(*) as num
FROM PERSON d, M_DIRECTOR md
WHERE d.Pid = md.Pid
GROUP BY d.Pid,d.name
HAVING COUNT(*) >= 10
order by count(*) desc
",conn)
You must use proper explicit joins between the tables and count on distinct movies:
select
p.name,
count(distinct d.mid) num
from person p
inner join m_director d on d.pid = p.pid
inner join movie m on m.mid = d.mid
group by p.pid, p.name
having num >= 10
order by num desc
Probably you have duplicate records in Person table - people with the same name but different ids. Try to group just by name and not by id
result = pd.read_sql_query("SELECT d.name,count(*) as num
FROM PERSON d, M_DIRECTOR md
WHERE d.Pid = md.Pid
GROUP BY d.name
HAVING COUNT(*) >= 10
order by count(*) desc
",conn)

SQL Unique Values

I have this query that joins 3 table. It appears to be working but I am getting duplicates. How can I remove the duplicates?
SELECT FIRST 100 e.email_id, e.location_id, e.email, l.location_type, p.salutation,
p.fname, p.lname
FROM email e, location l, person p
WHERE e.location_id = l.location_id
AND l.per_id = p.per_id
The simple answer is to add DISTINCT to your query.
SELECT FIRST 100 DISTINCT e.email_id, e.location_id, e.email, l.location_type, p.salutation, p.fname, p.lname
FROM email e, location l, person p
WHERE e.location_id = l.location_id
AND l.per_id = p.per_id
use Distinct
SELECT FIRST 100 Distinct e.email_id, e.location_id,
e.email, l.location_type, p.salutation,
p.fname, p.lname
FROM email e, location l, person p
WHERE e.location_id = l.location_id AND l.per_id = p.per_id
Since you are doing straight inner joins, you only get duplicate entries in the result set if there are duplicate entries in the input tables.
SELECT FIRST 100 e.email_id, e.location_id, e.email, l.location_type, p.salutation,
p.fname, p.lname
FROM email AS e
JOIN location AS l ON e.location_id = l.location_id
JOIN person AS p ON l.per_id = p.per_id
The most likely place for there to be trouble is in the 'location' table. You could establish that with a query such as:
SELECT location_id, per_id, COUNT(*)
FROM location
GROUP BY location_id, per_id
HAVING COUNT(*) > 1;
If this returns any data, then you have a pointer to where the trouble is. You should then examine why you don't have a unique constraint on the combination of location_id, per_id.