I have a query like below
Select Student_ID, Name, School
From Student S
Where S.Student_ID in ( select associate_id from Details D)
The output count is coming as expected
But now I have a new requirement to get additional column (D.Subject)in the data from the Details table
Select S.Student_ID, S.Name, S.School, D.Subject
From Student S
Where S.Student_ID in ( select associate_id from Details D)
When I’m trying to achieve the above by using the join like below the count is not matching . I tried both Left outer and inner join and the count doesn’t come out correctly .
Select S.Student_ID, S.Name, S.School, D.Subject
From Student S
Left outer join Details D on S.Student_ID = D.associate_id
Where S.Student_ID in ( select associate_id from Details D)
Please let me know how to achieve this
Since we dont have the sample data, I tried to put something together based on your question
problem is with the distinct count.
You should use distinct values in select. Dont really need the where condition, as that will be covered in your join condition.
Select distinct S.Student_ID, S.Name, S.School, D.Subject
From Student S join Details D on S.Student_ID = D.associate_id;
this will give you the unique counts there are. As there may be more join conditions between these tables and not just the column student_id to associate_id
for ex-
If i take the example below
and
in line query will give you a different count then inner join.
So either you find a correct join conditions or distinct the values to keep you close.
Related
My subquery:
select studentName, Course.dataStart
from Student,
Course
where Student.id in (select Course.id from Course);
I need a solution to this (above) subquery (not a join)
Why does the SQL subquery display one date for each name? (task: display the names of students from the Student table and the course start date from the Course table using a subquery)
With the help of Join, I get it as it should: (but I need to do it with a subquery)
You seem to be using implicit join syntax, but really you should be using an explicit inner join:
SELECT s.studentName, c.dataStart
FROM Student s
INNER JOIN Course c
ON c.id = s.course_id;
If you really wanted to use the implicit join syntax, it should be something like this:
SELECT s.studentName, c.dataStart
FROM Student s, Course c
WHERE c.id = s.course_id;
But again, please use the first version as its syntax is considered the best way to do it.
You can apply join :
SELECT S.studentName, C.dataStart
FROM Student S
INNER JOIN Course C
ON C.id = S.course_id;
With Sub query:
Select studentName, (Select Course.dataStart from Course
Where Course.id = course_id)
From Student
Asuming that Course.Id field is Student.Id (although it seems strange to me), I think the only way to get the results you want with a subquery would be using it in the SELECT clause:
select studentName, (SELECT Course.dataStart FROM Course WHERE Course.Id = Student.Id)
from Student
This would fail if you have more than 1 row in Course per Student, in that case you could use (SELECT DISTINCT Course.dataStart...)
I would like to take values from one table column and subtract those values from another column from another table.
I was able to achieve this by joining those tables and then subtracting both columns from each other.
Data from first table:
SELECT max_participants FROM courses ORDER BY id;
Data from second table:
SELECT COUNT(id) FROM participations GROUP BY course_id ORDER BY course_id;
Here is some code:
SELECT max_participants - participations AS free_places FROM
(
SELECT max_participants, COUNT(participations.id) AS participations
FROM courses
INNER JOIN participations ON participations.course_id = courses.id
GROUP BY courses.max_participants, participations.course_id
ORDER BY participations.course_id
) AS course_places;
In general, it works, but I was wondering, if there is some way to make it simplier or maybe my approach isn't correct and this code will not work in some conditions? Maybe it needs to be optimized.
I've read some information about not to rely on natural order of result set in databases and that information made my doubts to appear.
If you want the values per course, I would recommend:
SELECT c.id, (c.max_participants - COUNT(p.id)) AS free_places
FROM courses c LEFT JOIN
participations p
ON p.course_id = c.id
GROUP BY c.id, c.max_participants
ORDER BY 1;
Note the LEFT JOIN to be sure all courses are included, even those with no participants.
The overall number is a little tricker. One method is to use the above as a subquery. Alternatively, you can pre-aggregate each table:
select c.max_participants - p.num_participants
from (select sum(max_participants) as max_participants from courses) c cross join
(select count(*) as num_participants from participants from participations) p;
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
Hi I am looking to find out what join I would use if I wanted to join 2 tables together. I currently have a list of all students so 25 students to 1 class and the other table only shows 7 of those names with their test results.
What I would like is to have 1:1 join for the ones with the test results and the other ones without I would like to show them underneath so all in all I have 20 records.
If somebody could please advise on how I could achieve this please.
Thanks in advance.
It sounds like you want an OUTER JOIN.
For this example, we'll assume that there is a table named student and that it contains a column named id which is UNIQUE (or PRIMARY) KEY.
We'll also assume that there is another table named test_result which contains a column named student_id, and that column is a foreign key referencing the id column in student.
For demonstration purposes, we'll just make up some names for the other columns that might appear in these tables, name and score.
SELECT s.id
, s.name
, r.score
FROM student s
LEFT
JOIN test_result r
ON r.student_id = s.id
ORDER
BY r.student_id IS NULL
, s.score DESC
, s.id
Note that if student_id is not unique in test_result, there is potential to return multiple rows that match a row in student.
To get (at most) one row returned from test_result per student, we could use an inline view.
SELECT s.id
, s.name
, r.score
FROM student s
LEFT
JOIN ( SELECT t.student_id
, MAX(t.score) AS score
FROM test_result t
GROUP BY t.student_id
) r
ON r.student_id = s.id
ORDER
BY r.student_id IS NULL
, s.score DESC
, s.id
The expressions in the ORDER BY clause are designed to return the students that have matching row(s) in test_result first, followed by students that don't.
This is just a demonstration, and very likely excludes some important criteria, such as which test a score should be returned for. But without a sample schema and some example data, we're just guessing.
You are looking for a left outer join or a full outer join.
The left outer join will show all students and their tests if they have them.
select *
from Students as s
left outer join Tests as t
on s.StudentId = t.StudentId
The full outer join will show all students with their tests if they have them, and tests even if they do not have students.
select *
from Students as s
full outer join Tests as t
on s.StudentId = t.StudentId
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.