EXISTS Syntax in sql? - sql

I have two tables:
students(id, name, school_id)
schools(id, name)
I'm trying to use EXISTS in order to learn if there are any students that go to specific school, say "Harvard" for example. I know that EXISTS is used after WHERE but I'm wondering if I can do this:
SELECT EXISTS
(SELECT *
FROM students st, schools sch
WHERE st.school_id=sch.id AND sch.name="Harvard");
Is this query correct? I am working on MySQL Workbench and I don't get an error. But I don't know if it does what it's supposed to do.
If it's not, then what should I change? I just want to know if it's correct and if I can use this syntax in the future.
Note that the desired result is either yes or no (1 or 0).
How do I get this result?
Sorry if my question was unclear, I can edit it again if you still don't understand.

You could just get the count, then you would know if any exist - and if so, how many...
SELECT COUNT(*)
FROM students st, schools sch
WHERE st.school_id=sch.id AND sch.name="Harvard"
The EXISTS keyword is normally used as a pre-condition... i.e. "if not exists, then add this..."

This is a simple Select with a Join.
SELECT *
FROM Students S
JOIN Schools SC
ON S.School_id = SC.id
Where SC.Name = 'Harvard'
This will give you all the rows for the students that go to Harvard, if any. If you want to do a count you can do SELECT COUNT(*) instead or limit which columns are returned by indicating the specific columns in the SELECT statement

This will give you student names that go to Harvard. If you wish to see how many students learn at Harvard replace st.name with count(*).
Note that it doesn't matter what you put in SELECT list inside EXISTS statement, so choosing a constant value provides better performance than selecting columns.
SELECT
st.name
FROM
students st
WHERE
EXISTS(
SELECT 1 FROM schools s WHERE s.name= 'Harvard' AND s.id = st.school_id)
OR
SELECT
st.name
FROM
students st
INNER JOIN schools s ON
st.school_id = s.id
WHERE
s.name = 'Harvard'
Additional note: Code below would only yield result either true or false.
SELECT EXISTS ( <query> )
This means that below query would return true if there are any students that learn at Harvard.
SELECT EXISTS (
SELECT 1
FROM students st
INNER JOIN schools s ON st.school_id = s.id
WHERE s.name = 'Harvard' )

Related

How to display the desired rows of two tables using a subquery?

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...)

Use result of multiple rows to do arithmetic operation

I'm writing a query to multiply the count that I receive from subquery to fees amount, But I don't know how to do that. Any help/suggestion?
Oracle query is:
select courseid,coursename,fees*tmp
from course c join registration r on
r.courseid=c.courseid
and tmp IN (select count(*)
from course c join registration r on
r.courseid=c.courseid group by coursename);
I tried to use like a variable tmp ,But i don't think it works in oracle query. Is there an alternative way to do so?
You can't do that, because you can only select data from tables that appeared between FROM and WHERE. The IN operator is a quick way to save having to write a bunch of OR statements, it is not something that can establish a variable in the outer query.
Instead do something like:
select courseid,coursename,fees * COUNT(r.courseID) OVER(PARTITION BY c.coursename)
from course c join registration r on
r.courseid=c.courseid
Edit/update: you noted that this query produces too many rows and you only want to see distinct course names. In that case it would be better to just use the registrations table to count the number of people on the course and then multiply the fees:
SELECT
c.courseid, c.coursename, c.fees * COALESCE(r.numberOfstudents, 0) as courseWorth
FROM
course c
LEFT OUTER JOIN
(select courseid, COUNT(*) as numberofstudents FROM registration GROUP BY courseid) r
ON c.courseID = r.courseid
You can use a windowing function like Caius or you can use a join like this:
select courseid,coursename, fees * COALESCE(sub.cnt,0)
from course c
join registration r on r.courseid=c.courseid
left join (
select coursename, count(*) as cnt
from course c2
join registration r2 on r2.courseid=c2.courseid
group by coursename
) as sub;
note: I make no claim your joins are correct -- I'm basing this query off of your example not on any knowledge of your data model.

Where SQL column value not found in other column

I've read similar questions and I think I am doing it correct, but I just wanted to make sure my SQL is correct. (Still new to SQL)
I have 2 different tables
Students
id, name, address
Staff
id, name, address
I need to find the total number of students (who are not also staff)
SO I have the following SQL
create view nstudents as
select students.id
from students
LEFT JOIN staff ON staff.id = students.id;
Then I run the count(*) on the view.
Can someone confirm my SQL is correct or is there better way to do it?
Your LEFT JOIN doesn't eliminate students who are also staff, but it could be useful in achieving your goal. LEFT JOIN provides you with all results from the left table and matching results from the right table, or NULL results if the right table doesn't have a match. If you do this:
select count(*)
from students
LEFT JOIN staff ON staff.id = students.id
WHERE staff.id IS NULL;
I expect you'll get what you're looking for.
You might find it more natural to do something like this:
create view nstudents as
select s.id
from students s
where not exists (select 1 from staff st where st.id = s.id) ;
This should have the same performance as the left join.

Oracle performance issue Exists

I have a small application for schools and I face the next issue
I have a query on Oracle that supposed to fetch all teachers that has a specific student in there classes:
select * from teacher
where exists
(
select * from students
where teacher.teacher_id = students.teacher_id
and lower(student_name) like '%john%'
)
But my query is taking a long time, I tried to use IN or even JOIN but that didn't solve my problem:
select * from teacher
where teacher.teacher_id in
(
select students.teacher_id from students
where lower(student_name) like '%john%'
)
and this is using JOIN:
select * from teacher
JOIN
(select students.teacher_id from students
where lower(student_name) like '%john%') STUD
ON STUD.teacher_id = teacher_id
actually all are giving me the same result but I found that using EXISTS was the fastest
query, but still taking much time -about 10 min-.
I think that there might be a way using %rowtype and nested tables to solve the problem...
I am a beginner in Oracle, so if some body can help I will be graceful.
select distinct * from teacher
join student on teacher.teacher_id = student.teacher_id
where student_name ..
and there should be an index on teacher_id of student

Select where and where not

I have a table containing lessons that I called "cours" (french) and I have several cours inside and I have linked them to students with a table between them to see if they go to the lessons or not.
I would like to return data with the SELECT and the data that are NOT select.
So, If one student follow 3 courses of 5, I would like to return the 3 courses that he follow and the 2 courses that he doesn't follow.
Is there a way to do it ?
This will vary based on your RBDMS, but something similar to the following should work:
SELECT
s.Name,
l.Name,
CASE WHEN sl.StudentID IS NULL
THEN 'Not Follows'
ELSE 'Follows'
END AS Status
FROM
Student s
CROSS JOIN Lessons l
LEFT JOIN Student_Lessons sl
ON s.ID = sl.StudentID
AND l.ID = sl.LessonID
this is an outer join. if you identify your database engine (which may have specific outer join syntax) and your schema, then you can get some help with the actual SQL.