patternsqlMinor
Understanding a PostgreSQL join
Viewed 0 times
postgresqlunderstandingjoin
Problem
I have seen the following query in the PostgreSQL documentation. Unfortunately I don't understand the join criteria.
How I need to understand the JOIN clause?
What the tables are for and what the first query is doing are clear for me.
create temp table tmp_stat_user_tables as select * from pg_stat_user_tables;
select * from pg_stat_user_tables n
join tmp_stat_user_tables t
on n.relid=t.relid
and (n.seq_scan,n.idx_scan,n.n_tup_ins,n.n_tup_upd,n.n_tup_del) <>
(t.seq_scan,t.idx_scan,t.n_tup_ins,t.n_tup_upd,t.n_tup_del);How I need to understand the JOIN clause?
What the tables are for and what the first query is doing are clear for me.
Solution
I assume:
is what puzzles you. It means that if any of the columns differ the predicate is true. It is a shorter form of:
which in turn can be rewritten as
not sure if it makes it easier to grasp, but it can also be written using disjunctions
EDIT:
Nulls makes logical reasoning difficult so I created a small example to verify the logical equivalence of the expressions above. I think it is sufficient to use only two variables (http://sqlfiddle.com/#!15/73c52/2):
The following expressions corresponds to the ones I used above:
(n.seq_scan,n.idx_scan,n.n_tup_ins,n.n_tup_upd,n.n_tup_del) <>
(t.seq_scan,t.idx_scan,t.n_tup_ins,t.n_tup_upd,t.n_tup_del)is what puzzles you. It means that if any of the columns differ the predicate is true. It is a shorter form of:
NOT ( (n.seq_scan,n.idx_scan,n.n_tup_ins,n.n_tup_upd,n.n_tup_del) =
(t.seq_scan,t.idx_scan,t.n_tup_ins,t.n_tup_upd,t.n_tup_del) )which in turn can be rewritten as
NOT ( n.seq_scan = t.seq_scan AND
n.idx_scan = t.idx_scan AND
... )not sure if it makes it easier to grasp, but it can also be written using disjunctions
( n.seq_scan <> t.seq_scan OR
n.idx_scan <> t.idx_scan OR
... )EDIT:
Nulls makes logical reasoning difficult so I created a small example to verify the logical equivalence of the expressions above. I think it is sufficient to use only two variables (http://sqlfiddle.com/#!15/73c52/2):
create table s (x int);
insert into s(x) values (null),(0),(1);
create table t (x int, y int);
insert into t(x,y) select s1.x, s2.x from s s1 cross join s s2;The following expressions corresponds to the ones I used above:
select (t1.x,t1.y)<>(t2.x,t2.y) as a
, not( (t1.x,t1.y)=(t2.x,t2.y)) as b
, not ( t1.x = t2.x and t1.y = t2.y ) as c
, t1.x <> t2.x or t1.y <> t2.y as d
from t t1
cross join t t2;
a b c d
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
(null) (null) (null) (null)
true true true true
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
true true true true
true true true true
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
(null) (null) (null) (null)
false false false false
true true true true
true true true true
true true true true
true true true true
(null) (null) (null) (null)
true true true true
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
false false false false
true true true true
true true true true
true true true true
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
true true true true
true true true true
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
(null) (null) (null) (null)
true true true true
true true true true
true true true true
true true true true
(null) (null) (null) (null)
false false false false
true true true true
(null) (null) (null) (null)
true true true true
(null) (null) (null) (null)
true true true true
true true true true
true true true true
(null) (null) (null) (null)
true true true true
false false false falseCode Snippets
(n.seq_scan,n.idx_scan,n.n_tup_ins,n.n_tup_upd,n.n_tup_del) <>
(t.seq_scan,t.idx_scan,t.n_tup_ins,t.n_tup_upd,t.n_tup_del)NOT ( (n.seq_scan,n.idx_scan,n.n_tup_ins,n.n_tup_upd,n.n_tup_del) =
(t.seq_scan,t.idx_scan,t.n_tup_ins,t.n_tup_upd,t.n_tup_del) )NOT ( n.seq_scan = t.seq_scan AND
n.idx_scan = t.idx_scan AND
... )( n.seq_scan <> t.seq_scan OR
n.idx_scan <> t.idx_scan OR
... )create table s (x int);
insert into s(x) values (null),(0),(1);
create table t (x int, y int);
insert into t(x,y) select s1.x, s2.x from s s1 cross join s s2;Context
StackExchange Database Administrators Q#127606, answer score: 8
Revisions (0)
No revisions yet.