PostgreSQL 多个 USING 子句
PostgreSQL Multiple USING clause
我经常发现自己在 PostgreSQL 中使用(没有双关语意)USING 子句,并且想知道如何做出选择如果在同一个键名上有多个 USING。
让我用一个简单的例子来解释一下:
让 table A、B 和 C 具有 userid 列。
如果我这样做:
SELECT A.c1, A.c2, ...
FROM A
JOIN B USING(userid)
JOIN C USING(userid) ;
Postrges 如何管理因 tables B 和 C 都有列 userid 而引起的冲突?结果是什么?
A.userid = B.userid AND A.userid = C.userid
或
A.userid = B.userid AND B.userid = C.userid
希望我已经足够清楚了,提前感谢您的回答。
PS :我没有使用多个 USING 子句,因为我发现它不可读,但我想知道它是如何工作的。
如果使用USING
,join结果中只有一个userid
,所以不会有歧义。
所有 the documentation 不得不说的是
Furthermore, the output of JOIN USING
suppresses redundant columns:
但它也指列引用。您可以在没有 table 限定的情况下使用 userid
,并且不会出现“不明确的列引用”错误,因为 PostgreSQL 知道该列只存在一次。
使用内部联接,此查询:
SELECT A.c1, A.c2, ...
FROM A JOIN
B
USING (userid) JOIN
C
USING (userid) ;
相当于:
SELECT A.c1, A.c2, ...
FROM A JOIN
B
ON B.userid = A.userid JOIN
C
ON C.userid = A.userid ; -- or "C.userid = B.userid", it doesn't matter
请注意,NULL
值未通过 INNER JOIN
的比较,因此它们不是问题,因为它们不在结果集中。
对于LEFT OUTER JOIN
,逻辑同上。对于 FULL JOIN
:
SELECT A.c1, A.c2, ...
FROM A FULL JOIN
B
ON B.userid = A.userid FULL JOIN
C
ON C.userid = COALESCE(A.userid, B.userid) ;
请注意,在查询的其余部分 userid
中,没有限定,指的是 table.
中的非 NULL
值
您可以解释计划并检查:
CREATE TABLE a (
userid INT
, nm VARCHAR(32)
);
CREATE TABLE b (
userid INT
, adr VARCHAR(32)
);
CREATE TABLE c (
userid INT
, car VARCHAR(32)
);
EXPLAIN
SELECT *
FROM a
JOIN b USING(userid)
JOIN c USING(userid)
;
-- out QUERY PLAN
-- out -----------------------------------------------------------------------
-- out Merge Join (cost=152.17..334.01 rows=8946 width=250)
-- out Merge Cond: (a.userid = c.userid)
-- out -> Merge Join (cost=101.45..142.80 rows=2520 width=172)
-- out Merge Cond: (a.userid = b.userid)
-- out -> Sort (cost=50.72..52.50 rows=710 width=86)
-- out Sort Key: a.userid
-- out -> Seq Scan on a (cost=0.00..17.10 rows=710 width=86)
-- out -> Sort (cost=50.72..52.50 rows=710 width=86)
-- out Sort Key: b.userid
-- out -> Seq Scan on b (cost=0.00..17.10 rows=710 width=86)
-- out -> Sort (cost=50.72..52.50 rows=710 width=86)
-- out Sort Key: c.userid
-- out -> Seq Scan on c (cost=0.00..17.10 rows=710 width=86)
-- and with a full outer join:
EXPLAIN
SELECT *
FROM a
FULL JOIN b USING(userid)
FULL JOIN c USING(userid)
;
-- out QUERY PLAN
-- out -----------------------------------------------------------------------------
-- out Merge Full Join (cost=326.16..463.90 rows=8946 width=250)
-- out Merge Cond: (c.userid = (COALESCE(a.userid, b.userid)))
-- out -> Sort (cost=50.72..52.50 rows=710 width=86)
-- out Sort Key: c.userid
-- out -> Seq Scan on c (cost=0.00..17.10 rows=710 width=86)
-- out -> Sort (cost=275.43..281.73 rows=2520 width=172)
-- out Sort Key: (COALESCE(a.userid, b.userid))
-- out -> Hash Full Join (cost=25.98..133.06 rows=2520 width=172)
-- out Hash Cond: (a.userid = b.userid)
-- out -> Seq Scan on a (cost=0.00..17.10 rows=710 width=86)
-- out -> Hash (cost=17.10..17.10 rows=710 width=86)
-- out -> Seq Scan on b (cost=0.00..17.10 rows=710 width=86)
我经常发现自己在 PostgreSQL 中使用(没有双关语意)USING 子句,并且想知道如何做出选择如果在同一个键名上有多个 USING。
让我用一个简单的例子来解释一下: 让 table A、B 和 C 具有 userid 列。 如果我这样做:
SELECT A.c1, A.c2, ...
FROM A
JOIN B USING(userid)
JOIN C USING(userid) ;
Postrges 如何管理因 tables B 和 C 都有列 userid 而引起的冲突?结果是什么?
A.userid = B.userid AND A.userid = C.userid
或
A.userid = B.userid AND B.userid = C.userid
希望我已经足够清楚了,提前感谢您的回答。
PS :我没有使用多个 USING 子句,因为我发现它不可读,但我想知道它是如何工作的。
如果使用USING
,join结果中只有一个userid
,所以不会有歧义。
所有 the documentation 不得不说的是
Furthermore, the output of
JOIN USING
suppresses redundant columns:
但它也指列引用。您可以在没有 table 限定的情况下使用 userid
,并且不会出现“不明确的列引用”错误,因为 PostgreSQL 知道该列只存在一次。
使用内部联接,此查询:
SELECT A.c1, A.c2, ...
FROM A JOIN
B
USING (userid) JOIN
C
USING (userid) ;
相当于:
SELECT A.c1, A.c2, ...
FROM A JOIN
B
ON B.userid = A.userid JOIN
C
ON C.userid = A.userid ; -- or "C.userid = B.userid", it doesn't matter
请注意,NULL
值未通过 INNER JOIN
的比较,因此它们不是问题,因为它们不在结果集中。
对于LEFT OUTER JOIN
,逻辑同上。对于 FULL JOIN
:
SELECT A.c1, A.c2, ...
FROM A FULL JOIN
B
ON B.userid = A.userid FULL JOIN
C
ON C.userid = COALESCE(A.userid, B.userid) ;
请注意,在查询的其余部分 userid
中,没有限定,指的是 table.
NULL
值
您可以解释计划并检查:
CREATE TABLE a (
userid INT
, nm VARCHAR(32)
);
CREATE TABLE b (
userid INT
, adr VARCHAR(32)
);
CREATE TABLE c (
userid INT
, car VARCHAR(32)
);
EXPLAIN
SELECT *
FROM a
JOIN b USING(userid)
JOIN c USING(userid)
;
-- out QUERY PLAN
-- out -----------------------------------------------------------------------
-- out Merge Join (cost=152.17..334.01 rows=8946 width=250)
-- out Merge Cond: (a.userid = c.userid)
-- out -> Merge Join (cost=101.45..142.80 rows=2520 width=172)
-- out Merge Cond: (a.userid = b.userid)
-- out -> Sort (cost=50.72..52.50 rows=710 width=86)
-- out Sort Key: a.userid
-- out -> Seq Scan on a (cost=0.00..17.10 rows=710 width=86)
-- out -> Sort (cost=50.72..52.50 rows=710 width=86)
-- out Sort Key: b.userid
-- out -> Seq Scan on b (cost=0.00..17.10 rows=710 width=86)
-- out -> Sort (cost=50.72..52.50 rows=710 width=86)
-- out Sort Key: c.userid
-- out -> Seq Scan on c (cost=0.00..17.10 rows=710 width=86)
-- and with a full outer join:
EXPLAIN
SELECT *
FROM a
FULL JOIN b USING(userid)
FULL JOIN c USING(userid)
;
-- out QUERY PLAN
-- out -----------------------------------------------------------------------------
-- out Merge Full Join (cost=326.16..463.90 rows=8946 width=250)
-- out Merge Cond: (c.userid = (COALESCE(a.userid, b.userid)))
-- out -> Sort (cost=50.72..52.50 rows=710 width=86)
-- out Sort Key: c.userid
-- out -> Seq Scan on c (cost=0.00..17.10 rows=710 width=86)
-- out -> Sort (cost=275.43..281.73 rows=2520 width=172)
-- out Sort Key: (COALESCE(a.userid, b.userid))
-- out -> Hash Full Join (cost=25.98..133.06 rows=2520 width=172)
-- out Hash Cond: (a.userid = b.userid)
-- out -> Seq Scan on a (cost=0.00..17.10 rows=710 width=86)
-- out -> Hash (cost=17.10..17.10 rows=710 width=86)
-- out -> Seq Scan on b (cost=0.00..17.10 rows=710 width=86)