Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select * from table1 that does not exist in table2 with conditional

Tags:

sql

mysql

I have 2 tables. One is a table with things that can be learned. There is a JID that desribes each kind of row, and is unique to each row. The second table is a log of things that have been learned (the JID) and also the userid for the person that learned it. I am currently using this to select all of the data for the JID, but only the ones the user has learned based on userid.

SELECT * 
FROM tablelist1
LEFT JOIN tablelog2 ON (tablelist1.JID = tablelog2.JID) 
                       AND tablelog2.UID = 'php var'
WHERE tablelog2.JID IS NOT NULL

I now need to select the rows of things to learn, but only the things the userid has NOT already learned. I am obviously very new to this, bear with me. :) I tried using IS NULL, but while it seems it works, it gives duplicate JID's one being NULL, one being correct.

like image 496
user192738 Avatar asked Oct 21 '09 01:10

user192738


People also ask

How do I select data from one table is not in another table?

We can get the records in one table that doesn't exist in another table by using NOT IN or NOT EXISTS with the subqueries including the other table in the subqueries.

What is self join example?

A self join is a join in which a table is joined with itself (which is also called Unary relationships), especially when the table has a FOREIGN KEY which references its own PRIMARY KEY. To join a table itself means that each row of the table is combined with itself and with every other row of the table.

Which SQL command returns all records from one table and only matched records from a second table?

A CROSS JOIN , also known as a Cartesian JOIN, returns all rows from one table crossed with every row from the second table.

How do you write not in SQL?

Overview. The SQL Server NOT IN operator is used to replace a group of arguments using the <> (or !=)


2 Answers

Using LEFT JOIN/IS NULL:

   SELECT t.*
     FROM TABLE_LIST t
LEFT JOIN TABLE_LOG tl ON tl.jid = t.jid
    WHERE tl.jid IS NULL

Using NOT IN:

SELECT t.*
  FROM TABLE_LIST t
 WHERE t.jid NOT IN (SELECT tl.jid
                       FROM TABLE_LOG tl
                   GROUP BY tl.jid)

Using NOT EXISTS:

SELECT t.*
  FROM TABLE_LIST t
 WHERE NOT EXISTS(SELECT NULL
                    FROM TABLE_LOG tl
                   WHERE tl.jid = t.jid)

FYI
LEFT JOIN/IS NULL and NOT IN are equivalent in MySQL - they will perform the same, while NOT EXISTS is slower/less efficient. For more details: http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/

like image 55
OMG Ponies Avatar answered Sep 30 '22 22:09

OMG Ponies


First off, you should be using an INNER JOIN on your existing query:

SELECT * FROM tablelist1
    INNER JOIN tablelog2 ON (tablelist1.JID = tablelog2.JID) 
    WHERE tablelog2.UID = 'php var'

The way you're doing it you're getting all the rows from tablelist1, then going to extra trouble to exclude the ones that don't have a match in tablelog2. The INNER JOIN will do that for you, and more efficiently.

Secondly, to find for user "X" all the learnable-things that the user hasn't learned, do:

SELECT * FROM tablelist1 
    WHERE NOT EXISTS (SELECT JID FROM tablelog2 WHERE UID = 'X')
like image 23
Larry Lustig Avatar answered Sep 30 '22 23:09

Larry Lustig