patternsqlMinor
Can I write a FULL OUTER JOIN without OR IS NULL?
Viewed 0 times
canfullwithoutnulljoinwriteouter
Problem
Here's some data to play with:
Now I'd like to write a query that returns:
One possibility is:
This requires me to write
If this were a left join:
I could move the condition to the
Is there a way to do this with the full outer join as well?
Fiddle
CREATE TABLE a (
a_id int NOT NULL,
a_prop text NOT NULL
);
CREATE TABLE b (
b_id int NOT NULL,
b_prop text NOT NULL
);
INSERT INTO a VALUES (1, 'blah'), (2, 'blah'), (4, 'not this one');
INSERT INTO b VALUES (1, 'blah'), (3, 'blah'), (5, 'not this one');
Now I'd like to write a query that returns:
One possibility is:
SELECT *
FROM a
FULL OUTER JOIN b ON a_id = b_id
WHERE (a_prop = 'blah' OR a_prop IS NULL)
AND (b_prop = 'blah' OR b_prop IS NULL);
This requires me to write
OR ... IS NULL for every field that I have a condition on. This becomes even more verbose if some conditions are date ranges and the like.If this were a left join:
SELECT *
FROM a
LEFT JOIN b ON a_id = b_id
WHERE a_prop = 'blah'
AND (b_prop = 'blah' OR b_prop IS NULL);
I could move the condition to the
ON clause to avoid this:SELECT *
FROM a
LEFT JOIN b ON a_id = b_id AND b_prop = 'blah'
WHERE a_prop = 'blah';
Is there a way to do this with the full outer join as well?
Fiddle
Solution
without
Original:
Use
Or filter before joining:
The first version of the question asked for this predicate.
Original:
Use
Or filter before joining:
db<>fiddle here - showing all
Aside: Instead of
OR IS NULL?col = 'x' OR col IS NULLOriginal:
SELECT *
FROM a
FULL JOIN b ON a_id = b_id
WHERE (a_prop = 'blah' OR a_prop IS NULL)
AND (b_prop = 'blah' OR b_prop IS NULL);Use
col <> x IS NOT TRUE:SELECT *
FROM a
FULL JOIN b ON a_id = b_id
WHERE a_prop <> 'blah' IS NOT TRUE
AND b_prop <> 'blah' IS NOT TRUE;Or filter before joining:
SELECT *
FROM (SELECT * FROM a WHERE a_prop = 'blah') a
FULL JOIN (SELECT * FROM b WHERE b_prop = 'blah') b ON a_id = b_id;col <> 'x' OR col IS NULLThe first version of the question asked for this predicate.
Original:
SELECT *
FROM a
FULL OUTER JOIN b ON a_id = b_id
WHERE (a_prop <> 'not this one' OR a_prop IS NULL)
AND (b_prop <> 'not this one' OR b_prop IS NULL);Use
col IS DISTINCT FROM 'x':SELECT *
FROM a
FULL JOIN b ON a_id = b_id
WHERE a_prop IS DISTINCT FROM 'not this one'
AND b_prop IS DISTINCT FROM 'not this one';Or filter before joining:
SELECT *
FROM (SELECT * FROM a WHERE a_prop <> 'not this one') a
FULL JOIN (SELECT * FROM b WHERE b_prop <> 'not this one') b ON a_id = b_id;db<>fiddle here - showing all
Aside: Instead of
!= I use <>, which is the standard operator in SQL. (!= is an accepted alias in Postgres.)Code Snippets
SELECT *
FROM a
FULL JOIN b ON a_id = b_id
WHERE (a_prop = 'blah' OR a_prop IS NULL)
AND (b_prop = 'blah' OR b_prop IS NULL);SELECT *
FROM a
FULL JOIN b ON a_id = b_id
WHERE a_prop <> 'blah' IS NOT TRUE
AND b_prop <> 'blah' IS NOT TRUE;SELECT *
FROM (SELECT * FROM a WHERE a_prop = 'blah') a
FULL JOIN (SELECT * FROM b WHERE b_prop = 'blah') b ON a_id = b_id;SELECT *
FROM a
FULL OUTER JOIN b ON a_id = b_id
WHERE (a_prop <> 'not this one' OR a_prop IS NULL)
AND (b_prop <> 'not this one' OR b_prop IS NULL);SELECT *
FROM a
FULL JOIN b ON a_id = b_id
WHERE a_prop IS DISTINCT FROM 'not this one'
AND b_prop IS DISTINCT FROM 'not this one';Context
StackExchange Database Administrators Q#311321, answer score: 5
Revisions (0)
No revisions yet.