Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return row only if value doesn't exist

Tags:

sql

mysql

I have 2 tables - reservation:

   id  | some_other_column
   ----+------------------
   1   | value
   2   | value
   3   | value

And second table - reservation_log:

   id  | reservation_id | change_type
   ----+----------------+-------------
   1   | 1              | create
   2   | 2              | create
   3   | 3              | create
   4   | 1              | cancel
   5   | 2              | cancel

I need to select only reservations NOT cancelled (it is only ID 3 in this example). I can easily select cancelled with a simple WHERE change_type = cancel condition, but I'm struggling with NOT cancelled, since the simple WHERE doesn't work here.

like image 328
Madr Avatar asked Feb 07 '14 16:02

Madr


People also ask

How do you insert if row does not exist in SQL?

There are three ways you can perform an “insert if not exists” query in MySQL: Using the INSERT IGNORE statement. Using the ON DUPLICATE KEY UPDATE clause. Or using the REPLACE statement.

What does count Return in SQL if nothing is found?

The SQL COUNT() function returns the number of rows in a table satisfying the criteria specified in the WHERE clause. It sets the number of rows or non NULL column values. COUNT() returns 0 if there were no matching rows.


1 Answers

SELECT *
FROM reservation
WHERE id NOT IN (select reservation_id
                 FROM reservation_log
                 WHERE change_type = 'cancel')

OR:

SELECT r.*
FROM reservation r
LEFT JOIN reservation_log l ON r.id = l.reservation_id AND l.change_type = 'cancel'
WHERE l.id IS NULL

The first version is more intuitive, but I think the second version usually gets better performance (assuming you have indexes on the columns used in the join).

The second version works because LEFT JOIN returns a row for all rows in the first table. When the ON condition succeeds, those rows will include the columns from the second table, just like INNER JOIN. When the condition fails, the returned row will contain NULL for all the columns in the second table. The WHERE l.id IS NULL test then matches those rows, so it finds all the rows that don't have a match between the tables.

like image 56
Barmar Avatar answered Nov 03 '22 21:11

Barmar