I have 2 SQL tables. The 2 tables share 2 columns: external_id
of type int
and permission
of type text
:
CREATE TABLE A (
id serial PRIMARY KEY,
external_id int,
permission text,
something int,
rather text
);
CREATE TABLE B (
id serial PRIMARY KEY,
external_id int,
permission text,
random int,
life_story text
);
I want to select
all the distinct combinations of external_id
, permission
in table A
that DO NOT exist in table B
AND
vice-versa, all the distinct combinations of external_id
, permission
in table B
that DO NOT exist in table A
To clarify the query I'm trying to write, I turn to examples: If the tables look like this:
mwe=# select * from A;
id | external_id | permission | something | rather
----+-------------+------------+-----------+---------
1 | 1 | X | 1111 | bla bla
2 | 1 | P | 1111 | bla bla
3 | 2 | X | 1111 | bla bla
(3 rows)
mwe=# select * from B;
id | external_id | permission | random | life_story
----+-------------+------------+--------+------------
1 | 1 | X | 41 | bla bla
2 | 1 | P | 15 | bla bla
3 | 2 | X | 46 | bla bla
(3 rows)
The result of my query will be empty. because the distinct external_id
, permission
tuples for both tables are:
1| X
1| P
2| X
If the state of the tables is:
mwe=# select * from A;
id | external_id | permission | something | rather
----+-------------+------------+-----------+---------
1 | 1 | X | 1111 | bla bla
2 | 1 | P | 1111 | bla bla
3 | 2 | P | 1111 | bla bla
4 | 2 | X | 1111 | bla bla
5 | 2 | X | 2222 | bla bla
(5 rows)
mwe=# select * from B;
id | external_id | permission | random | life_story
----+-------------+------------+--------+------------
1 | 1 | X | 41 | bla bla
2 | 1 | X | 99 | one day along time ago
3 | 1 | P | 15 | bla bla
4 | NULL | X | 46 | bla bla
5 | 2 | X | 46 | bla bla
(5 rows)
the result of my query should be:
2 | P
NULL| X
because the distinct external_id
, permission
tuples for table A
are:
1| X # id=1
1| P # id=2
2| P # id=3
2| X # id=4,5
and the distinct external_id
, permission
tuples for table B
are:
1 | X # id=1,2
1 | P # id=3
NULL| X # id=4
2 | X # id=5
since 2| P
2| P
appears in the tuples we listed for table A
and does NOT appear in the tuples we listed for table B
, I want it to be returned as a result of my desired select query.
And since NULL| X
NULL| X
appears in the tuples we listed for table B
and does NOT appear in the tuples we listed for table A
, I want it to be returned as a result of my desired select query
For every other distinct external_id
, permission
tuples in any of the two tables, there is a matching tuple on the other table:
1 | X # table A id=1 table B id=1,2
1 | P # table A id=2 table B id=3
2 | X # table A id=4,5 table B id=5
I'm using Postgres 9.6
You can use NOT IN
on each side, and then UNION
both sides:
select distinct external_id, permission
from a
where (external_id, permission) not in (
select external_id, permission from b
)
or external_id is null and permission not in (
select permission from b where permission is null
)
union
select distinct external_id, permission
from b
where (external_id, permission) not in (
select external_id, permission from a
)
or external_id is null and permission not in (
select permission from a where permission is null
);
Result:
external_id permission
----------- ----------
2 P
<null> X
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.