outer join with not in and for each in sql - sql

This one has only one table with three columns student, lect and score. for each lecture I need to find the students who have not got any score.
I have written the below query which uses outer joins, but it can do so only for one lect at a time.
Eg: see below I passed 'L02'
How do I get this working for all the lect values as in (L01,L02,L03...etc)
select distinct * from
(
select distinct Student from import1
where lect ='L02'
)i1
right outer join
(select distinct Student from import1) i2
on i1.Student=i2.Student
where i1.Student is null
output of above is
This works for L02. But, how do I modify above to include for all lect values without hardcoding the values of lect?
Sample data from table:

Need a dataset of all possible student/lecture pairs. If the one table contains all the students and lectures that need to be considered, this dataset can be built with:
SELECT Student, Lect FROM (SELECT DISTINCT Student FROM import1) AS S, (SELECT DISTINCT Lect FROM import1) AS L
Otherwise, need a table of all students and a table of all lectures then query:
SELECT Student, Lect FROM Students, Lectures
Now join that query to the scores table with compound link on both identifier fields and use appropriate filter criteria.
SELECT Query1.Student, Query1.Lect, import1.Score
FROM Query1 LEFT JOIN import1
ON (Query1.Lect = import1.Lect) AND (Query1.Student = import1.Student)
WHERE Score Is Null;
Tested with an Access database.

Related

I want to select the highest value in a given joint table

I am working on two different tables. I want to join some of the information there and select the highest value in a particular column.
here is the code I am trying to use though not working
SELECT
result.matric_number, max(result.331), student.last_name, student.first_name, student.other_name
from result
INNER join student on result.result_id=student.StudentID
AND
student.Session = '2020/2021'
You have to use group by,If you are using aggregate function like max in the select statement.
Below query returns max(result) for the given group,result.matric_number, student.last_name, student.first_name, student.other_name
SELECT result.matric_number, max(result.331), student.last_name, student.first_name, student.other_name
from result INNER join student
on result.result_id=student.StudentID AND student.Session = '2020/2021'
group by result.matric_number, student.last_name, student.first_name, student.other_name
If you want max of all the records then remove all columns in select execpt max
SELECT max(result.331)
from result INNER join student
on result.result_id=student.StudentID AND student.Session = '2020/2021'

Subtracting values of columns from two different tables

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;

SQL Server : get unique ID from one table, another table, or both

I have two tables, TA and CMI, that contain a person_ID. The ID may exist in TA, it may exist in CMI, or it may exist in both. I want a distinct list of ALL person_ID's regardless whether they are in TA, CMI, or both tables.
I also want to be able to select them where their question_ID's are the same. However, the question_id's have different column names: TA.question and CMI.sco = question_id.
EDIT:
So, if I also wanted to do the select on question as I stated earlier AND a join to the person table, it would look something like:
select ta.person_id, person_key
from ta
left join person on person.person_id = ta.person_id
where question=7033
union -- on purpose to remove duplicates
select cmi.person_id, person_key
from cmi
left join person on person.person_id = cmi.person_id
where sco=7033
You would use union:
select person_id
from ta
union -- on purpose to remove duplicates
select person_id
from cmi;
You can use this as a CTE or subquery in a query.

SQL Server : resultset zero totals for values that don't exist

SQL Fiddle
I'm trying to force through zero values for grades that don't exist in my Results table, but do exist in my list of possible Grades table.
I've managed to join tables successfully in order to almost achieve this using this previous post as guidance up to a point.
As you can see from my fiddle the resultset is displaying NULL values for my Year and Subject columns and I would like these to display the relevant subject.
Don't use * in SELECT instead use specify the colums you need and use ISNULL and make it as zero like:
SELECT ISNULL(t.amount,0)
FROM [yourtable] y
left join [someOtherTable] t
ON y.id=t.id
What you need is a table of Subjects and Years, then cross join for grades...
create table Subjects(SubjectID INT, Subject Varchar(50));
create table YearSub (SubjectID INT, Year INT, CrateDate Date); -- Map your available subjects for each year in here
Once you have thiese, make a CTE to hold the full list of available subjects, years and grades
with AllGrades as
(select SubjectID, Year, Grade
from YearSub YS
cross join Grades
)
select ...
from AllGrades
left join ...
And so on
i think this is what you wanted.
first you get all combinition of student & grades by using CROSS JOIN
then you LEFT JOIN to the resutl table to the get the count
select s.year, subject grade, grade, count(wag) as Total
from student s
cross join grades g
left join results r on s.upn = r.upn and s.upn = r.upn
group by s.year, g.grade

How to add Average into subquery

So I tried a nested subquery to join three tables together to get the columns needed.
SELECT CAPACITY, Course.COURSE_NAME, SEMESTER
FROM COURSE, Section, Room
WHERE Section.COURSE_NUM
IN (SELECT Course.COURSE_NUMBER
FROM Course
WHERE SEMESTER='FALL' AND Section.ROOM
IN (SELECT Room.ROOM
FROM Room
WHERE AVG(CAPACITY)>CAPACITY
)
)
I had it all right before the second subquery I just need the Column capacity to display results greater then the average of the column. So this was the output before the nested subquery.
SELECT CAPACITY, Course.COURSE_NAME, SEMESTER
FROM COURSE, Section, Room
WHERE Section.COURSE_NUM
IN (SELECT Course.COURSE_NUMBER
FROM Course
WHERE SEMESTER='FALL'
)
I just need to be able to display the Column Capacity results that are greater then its average number.
I cannot tell by this that which table has the Capacity column and what is the relationship between the tables you have there, but all i can say is that you need to join the 3 tables again in the subquery to be able to access the Capacity there, somthing like this:
SELECT CAPACITY, Course.COURSE_NAME, SEMESTER
FROM COURSE, Section, Room
WHERE Section.COURSE_NUM
IN (SELECT Course.COURSE_NUMBER
FROM Course
WHERE SEMESTER='FALL' AND Section.ROOM
IN(
SELECT Room.ROOM
FROM Room
INNER JOIN SEMESTER
ON COLUMNS
INNER JOIN SECTION
ON COLUMNS
INNER JOIN COURSE
ON COLUMNS
WHERE AVG(CAPACITY)>CAPACITY
)
I seemed to be able to figure it out.
SELECT CAPACITY, Course.COURSE_NAME, SEMESTER
FROM COURSE, Section, Room
WHERE Section.COURSE_NUM
IN (SELECT Course.COURSE_NUMBER
FROM COURSE
WHERE SEMESTER='FALL' AND Room.ROOM
IN (SELECT Section.ROOM
FROM Section
WHERE CAPACITY>(SELECT AVG(CAPACITY) FROM Room)))
ORDER BY CAPACITY