【问题标题】:PostgreSQL Multiple USING clausePostgreSQL 多重 USING 子句
【发布时间】:2020-09-25 08:49:02
【问题描述】:

我经常发现自己在 PostgreSQL 中使用(不是双关语)USING 子句,并且想知道在多个 USING 的情况下如何做出选择 在同一个键名上。

让我用一个简单的例子来解释: 让表 A、B 和 C 具有 userid 列。 如果我在做:

SELECT A.c1, A.c2, ...
FROM A
JOIN B USING(userid)
JOIN C USING(userid) ;

Postrges 如何处理由于表 B 和 C 都有列 userid 而产生的冲突?输出结果是什么?

A.userid = B.userid AND A.userid = C.userid

A.userid = B.userid AND B.userid = C.userid 

我希望我已经足够清楚了,提前感谢您的回答。

PS:我没有做多个 USING 子句,因为我发现它不可读,但我想知道它是如何工作的。

【问题讨论】:

  • JOIN C USING(userid) 使用上一次加入的唯一用户 ID,既不是 A 也不是 B。
  • 您的问题涉及查询的处理顺序。如前所述,解释计划将向您展示您系统上的流程以及您目前的数据量。然而,这个顺序不是固定的。优化器根据可用索引、表大小、当前统计信息等选择操作顺序。随着这些变化,计划本身也(可能)发生变化。

标签: sql postgresql using


【解决方案1】:

使用内部连接,此查询:

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 没有限定条件,指的是任何表中的非NULL 值。

【讨论】:

    【解决方案2】:

    如果使用USING,则连接结果中将只有一个userid,因此不会有歧义。

    所有the documentation不得不说是

    此外,JOIN USING 的输出抑制了冗余列:

    但它也指列引用。您可以使用 userid 而不使用表限定,并且不会收到“不明确的列引用”错误,因为 PostgreSQL 知道该列只存在一次。

    【讨论】:

    • 只要这些连接是内连接就可以了,但是如果连接是外连接呢?至少语法允许。
    • 然后得到非空值。
    • 谢谢。有道理,我刚刚检查了 SQL 标准,它实际使用 COALESCE 定义的结果。
    【解决方案3】:

    您可以解释计划并检查:

    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)
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-09
      • 2014-01-14
      • 2012-05-13
      • 1970-01-01
      • 2012-08-07
      • 2016-07-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多