tags:

views:

395

answers:

5

I'm having a brain-dead moment... I have two tables described by:

CREATE TABLE table_a (
    id             INTEGER          PRIMARY KEY AUTO_INCREMENT,
    name           VARCHAR(255)     NOT NULL
    UNIQUE (name))

CREATE TABLE table_b (
    id             INTEGER          PRIMARY KEY AUTO_INCREMENT,
    a_key          INTEGER          NOT NULL,
    other_stuff    VARCHAR(255)     NOT NULL,
    FOREIGN KEY(a_key)  REFERENCES table_a(id)
         ON DELETE CASCADE)

How can I select all rows from table_a that do not have an entry in table_b.a_key?

+2  A: 

Naively, you can use a NOT EXISTS subquery:

SELECT A.*
FROM table_a A
WHERE NOT EXISTS (
  SELECT 1
  FROM table_b B
  WHERE B.a_key = A.id
)

You can also try an outer join. But they'll usually optimize to the same query internally.

Welbog
+1  A: 
SELECT 
table_a.* 
FROM table_a 
LEFT JOIN table_b 
ON table_a.id = table_b.a_key 
WHERE b.id IS NULL;

This does a JOIN on table_a and table_b and where the JOIN finds no join result for table_b, it prints the corresponding row entry for table_a.

Phil
+1  A: 

If it is SQL server 2005+ you could try EXCEPT

SELECT id
FROM table_a
EXCEPT
SELECT a_key
FROM table_b;
edosoft
+7  A: 
SELECT table_a.*
FROM table_a
    LEFT JOIN table_b
        ON table_a.id = table_b.a_key
WHERE table_b.id IS NULL
LukeH
A: 
select a.*
from table_a a
where a.id not in (select b.a_key from table_b b where b.a_key = a.id)
Bigballs
It's noteworthy that NOT IN (...) fails subtly when the sub-select returns a list containing NULL values. In this case it can't happen (a_key is defined as INT NOT NULL), but it's the reason for me to avoid it for this type of query.
Tomalak
thanks for the explanation
Bigballs
NOt in is usually slower than a left join as well
HLGEM