Count, inner join - sql

I have two tables:
DRIVER(Driver_Id,First name,Last name,...);
PARTICIPANT IN CAR ACCIDENT(Participant_Id,Driver_Id-foreign key,responsibility-yes or no,...).
Now, I need to find out which driver participated in accident where responsibility is 'YES', and how many times. I did this:
Select Driver_ID, COUNT (Participant.Driver_ID)as 'Number of accidents'
from Participant in car accident
where responsibility='YES'
group by Driver_ID
order by COUNT (Participant.Driver_ID) desc
But, I need to add drivers first and last name from the first table(using inner join, I suppose). I don't know how, because it is not contained in either an aggregate function or the GROUP BY clause.
Please help :)

As you suspected, you need to use an inner join. And because the first name and last name are now part of the SELECT, you also need to include those columns in the GROUP BY.
Select Driver_ID, First_name, Last_name COUNT (Participant.Driver_ID) as "Number of accidents"
from "Participant in car accident" join Driver on "Participant in car accident".Driver_ID = Driver.Driver_ID
where responsibility='YES'
group by Driver_ID, First_name, Last_name
order by COUNT (Participant.Driver_ID) desc
Is this homework?

You could use an inline table:
SELECT d.driver_first_name,
d.driver_last_name,
r.incident_count
FROM DRIVER d
INNER JOIN (SELECT driver_id,
count(*) incident_count
FROM PARTICIPANT_IN_CAR_ACCIDENT
WHERE responsibility = 'YES'
GROUP BY driver_id) r
ON d.driver_id = r.driver_id
ORDER BY r.incident_count DESC
Should work.

Related

sql query with patients

Need help with a database query;
patients(cpr(key), firstname, sirname, address, postalnumber, country, journal)
allergies(allergens(key)), allergytype, allergic_reaction)
patientallergies(allergens(key), cpr(key))
How do we write CPR-numbers pairwise on patients who are allergic against the exact same allergens? A CPR number can only be printed once and a CPR number cannot be paired with itself.
Our current suggestion goes something like this:
SELECT p1.cpr, p2.cpr
FROM patients p1, patients p2
Not sure where to go from here
One method is a self-join and aggregation. This uses window functions to count the number of allergens per patient to be sure the match is exact:
with pa as (
select pa.*, count(*) over (partition by cpr) as cnt
from patientallergies pa
)
select pa.cpr, pa2.cpr
from pa join
pa pa2
on pa.allergan = pa2.allergan and pa.cnt = pa2.cnt
group by pa.cpr, pa2.cpr, pa.cnt
having count(*) = pa.cnt;

Combining FREQUENCY count and INNER CASE in SQL

How do I combine both in order to show the student name (sname) and section number (sectno) for a class that has more than 6 student? So far I have this
SELECT student.sname, enroll.sectno,
FROM student
INNER JOIN enroll
ON student.sid=enroll.sid
with
SELECT grade,
COUNT(grade)AS Frequency
FROM enroll
GROUP BY grade
HAVING COUNT(grade)>6
looks like you were very close. I think the below should work for you:
SELECT
student.sname,
enroll.sectno,
COUNT(enroll.grade) AS Frequency
FROM student
INNER JOIN enroll ON student.sid=enroll.sid
GROUP BY student.sname, enroll.sectno
HAVING COUNT(enroll.grade)>6
In your 2md Select there's no relation to a class that has more than 6 student, IMHO the GROUP BY should be based on column like classid. And then you can simply combine both using a Windowed Aggregate:
with cte as
(
SELECT student.sname, enroll.sectno,
-- get the count per class, might be a different column than sectno
count(*) over (partition by enroll.sectno) as cnt
FROM student
INNER JOIN enroll
ON student.sid=enroll.sid
)
select * from cte
where cnt > 6

Why don't the values for a single studentid add up while i execute this SQL statement even though i used Distinct?

I have to write a query to display the studentid and the total fees paid by each student and then sort the result based on studentid in ascending order.
I have used Distinct so that studid is displayed only once but still I don't get the expected output.
My code:
select distinct s.studid,c.fees as total_fees from Student s join
Registration r on s.studid=r.studid join Course c on r.courseid=c.courseid
group by s.studid,c.fees order by s.studid;
My Output:
Expected Output:
You join registration.
That would give you one record per student and registration,
which is what you want.
Calling distinct on it then, though, means you only get one of those records.
What you want to do is sum up those fees, group the results per student, and order by studid.
SELECT s.studid, SUM(c.fees) as total_fees FROM student s
JOIN registration r ON s.studid = r.studid
JOIN course c ON r.courseid=c.courseid
GROUP BY s.studid
ORDER BY s.studid;
You are querying by distinct combination of the student ID and the fees instead of summing the fees:
SELECT s.studid, SUM(c.fees) as total_fees
FROM student s
JOIN registration r ON s.studid = r.studid
JOIN course c ON r.courseid=c.courseid
GROUP BY s.studid
ORDER BY s.studid ASC

Problems selecting columns with aggregates (SQL Server)

I'm seriously stuck. Please bear with me though because I'm new to databases.:)
Anyway, I need to display the StudentID, the subject where the student has the highest grade in, and the grade of that subject.
Here's the code I have:
SELECT
Grades.Student_ID,
Subject.Subject_Code,
MAX(Grades.Grade)
FROM
Grades
LEFT JOIN
Subject ON Grades.Subject_ID = Subject.Subject_ID
GROUP BY
Grades.Student_ID
But it has this error:
'Subject.Subject_Code' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.'
But I can't include Subject_Code in GROUP BY because the results will be different.
What can I do to only show the
Student_ID || (subject with highest grade) || (grade of that subject)
How can I work around this error?
It seems you are looking for a group wise maximum. Here's one approach joining back to a derived table containing the top grade for each student (This approach should work on most RDBMS, including MySql):
SELECT X.Student_ID,
s.Subject_Code,
x.TopGrade
FROM
(
SELECT
Grades.Student_ID,
MAX(Grades.Grade) AS TopGrade
FROM Grades
GROUP BY Grades.Student_ID
) x
INNER JOIN Grades g
ON g.Student_ID = x.Student_ID AND g.Grade = x.TopGrade
LEFT JOIN Subject s
ON g.Subject_ID = s.Subject_ID
If the same student has two or more marks with exactly the same grade, it will return all Subjects.
Here's my original answer, which will work on SQL Server
SELECT x.Student_ID, x.Subject_Code, x.Grade
FROM
(
SELECT
Grades.Student_ID,
Subject.Subject_Code,
RANK() OVER (PARTITION BY Grades.Student_ID ORDER BY Grades.Grade DESC) AS [Rank],
Grades.Grade
FROM Grades
LEFT JOIN Subject
ON Grades.Subject_ID = Subject.Subject_ID
) x
WHERE x.[Rank] = 1;
SqlFiddle of both the above queries here. In addition, there is an example with ROW_NUMBER with an additional arbitrary ORDER BY to pick one top subject when the student has equal marks in two or more subjects.

How do I count from 2 different tables in access sql

I have two tables, one that contains information about patients visits: PatientName,DoctorName,DataOfVisit, etc and the second table that contains information about doctors: DoctorName and DoctorSpeciality.
I need to create a query that will print me the PatientName, the number of doctors that patient went to, and the number of different specialties.
If I run
SELECT PatientName, COUNT(VISITS.DoctorName) as DocNum, Count(DoctorSpeciality) as SpecNum
FROM VISITS
INNER JOIN Doctors
ON VISITS.DoctorName = Doctors.DoctorName
GROUP BY PatientName, VISITS.DoctorName, DoctorSpeciality
I get the number of Doctors but not the number of Specialities and the patients are not grouped.
In most databases, you would just use count(distinct specialty). But, Access doesn't support that.
You can do what you want with two group bys:
SELECT PatientName, COUNT(*) as NumSpecialties, SUM(NumDocs) as NumDocs
FROM (SELECT PatientName, Doctors.DoctorSpeciality, COUNT(*) as NumDocs
FROM VISITS INNER JOIN
Doctors
ON VISITS.DoctorName = Doctors.DoctorName
GROUP BY PatientName, DoctorSpeciality
) as pd
GROUP BY PatientName;
You can add DISTINCT within your COUNT() function, also you should not include the aggregate fields in your GROUP BY.
Here is how I would change the query.
SELECT PatientName, COUNT(DISTINCT VISITS.DoctorName) as DocNum,
Count(DISTINCT DoctorSpeciality) as SpecNum
FROM VISITS INNER JOIN
Doctors ON VISITS.DoctorName = Doctors.DoctorName
GROUP BY PatientName
use table name with fields that you want to select from db
SELECT VISITS.PatientName, COUNT(VISITS.DoctorName) as DocNum, Count(Doctors.DoctorSpeciality) as SpecNum
FROM VISITS
INNER JOIN Doctors
ON VISITS.DoctorName = Doctors.DoctorName
GROUP BY PatientName, VISITS.DoctorName, DoctorSpeciality