SQL中join后的on和where的过滤条件的区别

 

1、原理

1.1连接基本概念

(1)内连接(inner join、join):必须完全满足连接运算(natural、using、on)的左右表数据行。

(2)左外连接(left outer join、left join):仅保留左表在连接运算之前的数据行,无匹配的右表列填充null。

(3)右外连接(right outer join、right join):仅保留右表在连接运算之前的数据,无匹配的左表列填充null。

(4)全外连接(full outer join、full join):保留左右表在连接运算之前的数据,无匹配的左表或右表列填充null。

(5)交叉连接(cross join):没有on或者using,因此无需讨论。

1.2说明

(1)内连接中,on过滤条件可以被where过滤条件取代,反之亦然。在on后边写连接条件where后边写其余条件的优点是可读性好。

(2)外连接中,on过滤条件和where过滤条件不同,外连接运算将不符合on过滤条件的行当作空值行存在,也就是行存在把列值抹去。

2、验证

2.1创建表

分别对左外连接中左表和右表上的ON和WHERE过滤条件进行验证。

首先创建两张表和示例数据,简单起见没有创建索引和外键:

CREATE TABLE books (

  id char(2) PRIMARY KEY,

  title varchar(20) NOT NULL,

  primary_author_id char(2) NOT NULL -- 关联authors.id

);

CREATE TABLE authors (

  id char(2) PRIMARY KEY,

  fullname varchar(20) NOT NULL

);

INSERT INTO books VALUES

('B0', '三国演义', 'A0'),

('B1', '货币战争', 'A1'),

('B2', '水浒传', 'A2');

INSERT INTO authors VALUES

('A0', '罗贯中'),

('A2', '吴承恩'),

('A3', '金庸');

2.2books表on过滤条件

SELECT a.title, b.fullname

FROM books a

LEFT JOIN authors b

ON a.primary_author_id = b.id

AND a.title = '三国演义';

 

查询计划1(EXPLAIN (analyze, costs off, timing off, summary off) 后边跟随SQL语句):

 Hash Left Join (actual rows=3 loops=1)

   Hash Cond: (a.primary_author_id = b.id)

   Join Filter: ((a.title)::text = '三国演义'::text)

   Rows Removed by Join Filter: 1

   ->  Seq Scan on books a (actual rows=3 loops=1)

   ->  Hash (actual rows=3 loops=1)

         Buckets: 1024  Batches: 1  Memory Usage: 9kB

         ->  Seq Scan on authors b (actual rows=3 loops=1)

 

查询结果1:

  title   | fullname

----------+----------

 三国演义 | 罗贯中

 货币战争 |

 水浒传   |

2.3books表WHERE过滤条件

SELECT a.title, b.fullname

FROM books a

LEFT JOIN authors b

ON a.primary_author_id = b.id

WHERE a.title = '三国演义';

 

查询计划2:

 Hash Right Join (actual rows=1 loops=1)

   Hash Cond: (b.id = a.primary_author_id)

   ->  Seq Scan on authors b (actual rows=3 loops=1)

   ->  Hash (actual rows=1 loops=1)

         Buckets: 1024  Batches: 1  Memory Usage: 9kB

         ->  Seq Scan on books a (actual rows=1 loops=1)

               Filter: ((title)::text = '三国演义'::text)

               Rows Removed by Filter: 2

 

查询结果2:

  title   | fullname

----------+----------

 三国演义 | 罗贯中

2.4authors表ON过滤条件

SELECT a.title, b.fullname

FROM books a

LEFT JOIN authors b

ON a.primary_author_id = b.id

AND b.fullname = '罗贯中';

 

查询计划3:

 Hash Left Join (actual rows=3 loops=1)

   Hash Cond: (a.primary_author_id = b.id)

   ->  Seq Scan on books a (actual rows=3 loops=1)

   ->  Hash (actual rows=1 loops=1)

         Buckets: 1024  Batches: 1  Memory Usage: 9kB

         ->  Seq Scan on authors b (actual rows=1 loops=1)

               Filter: ((fullname)::text = '罗贯中'::text)

               Rows Removed by Filter: 2

 

查询结果3:

  title   | fullname

----------+----------

 三国演义 | 罗贯中

 货币战争 |

 水浒传   |

2.5authors表WHERE过滤条件

SELECT a.title, b.fullname

FROM books a

LEFT JOIN authors b

ON a.primary_author_id = b.id

WHERE b.fullname = '罗贯中';

查询计划4:

 Hash Join (actual rows=1 loops=1)

   Hash Cond: (a.primary_author_id = b.id)

   ->  Seq Scan on books a (actual rows=3 loops=1)

   ->  Hash (actual rows=1 loops=1)

         Buckets: 1024  Batches: 1  Memory Usage: 9kB

         ->  Seq Scan on authors b (actual rows=1 loops=1)

               Filter: ((fullname)::text = '罗贯中'::text)

               Rows Removed by Filter: 2

 

查询结果4:

  title   | fullname

----------+----------

 三国演义 | 罗贯中

posted on 2023-05-29 14:36  一只小白two  阅读(1160)  评论(0编辑  收藏  举报