Reputation: 9871
I have an item
table, which has a foreign key reference to a tax
table. The column is tax_id
.
I used to have the tax_id
as NOT NULL
in my schema, however I just changed this because I want it to be optional, so now it is NULL DEFAULT NULL
in the schema.
This has broken my query. Now when I query for items and join the taxes, I only get the ones where the tax_id
field matches.
This is my query:
SELECT item.*
FROM item
JOIN user_item
ON user_item.item_id = item.id
JOIN tax
ON tax.id = item.tax_id
WHERE user_item.user_id = ?
AND item.deleted_at IS NULL
AND user_item.deleted_at IS NULL
AND tax.deleted_at IS NULL
This query works, however if I am given the items below:
+----+--------+--------------------+-------------+-------+---------------------+------------+------------+
| id | tax_id | name | description | price | created_at | updated_at | deleted_at |
+----+--------+--------------------+-------------+-------+---------------------+------------+------------+
| 1 | 2 | foo | | 1.13 | 2017-07-30 15:20:14 | NULL | NULL |
| 2 | NULL | bar | | 0.67 | 2017-07-30 15:20:25 | NULL | NULL |
| 3 | NULL | baz | | 1.15 | 2017-07-30 15:22:33 | NULL | NULL |
+----+--------+--------------------+-------------+-------+---------------------+------------+------------+
Then the query only returns the item with id 1. I want id 2 and 3 as well.
How can I modify my query to achieve this?
I understand the problem of the query is this part: ON tax.id = item.tax_id
.
Upvotes: 1
Views: 216
Reputation: 1271151
I think the best approach is to put the deleted_at
condition in the on
clause. If you want NULL
values to match between the tables, then write this as:
SELECT i.*
FROM item i JOIN
user_item ui
ON ui.item_id = i.id LEFT JOIN
tax t
ON NOT (t.id <=> i.tax_id) AND -- ids are the same or both `NULL`.
t.deleted_at IS NULL
WHERE ui.user_id = ? AND
i.deleted_at IS NULL AND
ui.deleted_at IS NULL ;
Upvotes: 1
Reputation: 312259
This is exactly what left join
s are for:
SELECT item.*
FROM item
JOIN user_item
ON user_item.item_id = item.id
LEFT JOIN tax -- Here!
ON tax.id = item.tax_id
WHERE user_item.user_id = ?
AND item.deleted_at IS NULL
AND user_item.deleted_at IS NULL
AND tax.deleted_at IS NULL
Upvotes: 2