0

I have 3 tables course, grade and evaluation. I want comparing two tables grade and evaluation . if the data in the table grade does not exist in the table evaluation , then the data will appear (output)

table and output

" select Grade.ID_Courses,Course.ID_Courses,Grade.NAME, Course.NAME, Grade.ID_Courses, Evaluation.NAME, Evaluation.Year, Grade.Year from Grade, Course, Evaluation WHERE Grade.ID_Courses=Course.ID_Courses AND Grade.NAME=JOHN and Grade.Year=1 and Evaluation.NAME=GRADE.NAME and Grade.ID_Courses NOT IN (SELECT ID_Courses FROM Evaluation where NAME=JOHN and Year=1 ) GROUP BY Grade.ID_Courses" 

the problem is when the name john is not in the table evaluation then there is no output comes out .

3
  • 1
    avoid not in. try not exists or left join patterns Commented Aug 24, 2015 at 6:17
  • That is a good Query! Commented Aug 24, 2015 at 6:18
  • for that matter, try explicit join patterns ! Commented Aug 24, 2015 at 6:19

2 Answers 2

2

Avoid NOT IN like the plague if

SELECT ID_Courses FROM Evaluation where `NAME`='JOHN' and Year=1 

could ever contain NULL. Instead, use NOT EXISTS or Left Joins

use explicit joins, not 1980's style joins using the WHERE clause

To illustrate the misery of NOT IN:

SQL NOT IN () danger

create table mStatus ( id int auto_increment primary key, status varchar(10) not null ); insert mStatus (status) values ('single'),('married'),('divorced'),('widow'); create table people ( id int auto_increment primary key, fullName varchar(100) not null, status varchar(10) null ); 

Chunk1:

truncate table people; insert people (fullName,`status`) values ('John Henry','single'); select * from mstatus where `status` not in (select status from people); 

** 3 rows, as expected **

Chunk2:

truncate table people; insert people (fullName,`status`) values ('John Henry','single'),('Kim Billings',null); select * from mstatus where status not in (select status from people); 

no rows, huh?

Obviously this is 'incorrect'. It arises from SQL's use of three-valued logic, driven by the existence of NULL, a non-value indicating missing (or UNKNOWN) information. With NOT IN, Chunk2 it is translated like this:

status NOT IN ('married', 'divorced', 'widowed', NULL) 

This is equivalent to:

NOT(status='single' OR status='married' OR status='widowed' OR status=NULL) 

The expression "status=NULL" evaluates to UNKNOWN and, according to the rules of three-valued logic, NOT UNKNOWN also evaluates to UNKNOWN. As a result, all rows are filtered out and the query returns an empty set.

Possible solutions include:

select s.status from mstatus s left join people p on p.status=s.status where p.status is null 

or use not exists

Sign up to request clarification or add additional context in comments.

1 Comment

This is an extreme 'gotcha'! Despite being well-versed in the perils of null, here I would've just unconsciously assumed that although the known values are compared using =, the null would be compared using is null semantics. Of course, it isn't, and = null generates an unknown result, which invalidates the rest of it, and the whole thing falls apart. (I seem to recall being baffled by this in the past, and presumably being saved by an SO answer, though probably not this one as I wasn't using PHP. :D)
0

Try using joins to solve this

select g.*, e.*,c.* from grade g inner join evaluation e on g.ID_COURSES <> e.ID_COURSES and g.year <> e.year inner join COURSE c on c.ID_COURSES = g.ID_COURSES ; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.