PostgreSQL数据库创建并使用视图以及子查询

PostgreSQL 视图、子查询

Posted in PostgreSQL onApril 11, 2022

视图

表里面保存的是实际数据,视图里面保存的是SELECT语句(视图本身不存储数据)。

从视图中读取数据,此时视图在内部执行SELECT语句,创建一张临时表。

使用视图的好处:其一,视图不保存数据,节省存储设备容量。其二,将频繁使用的SELECT语句保存成视图,每次使用这些语句时候,不用重复书写,只需调用视图。其三,数据保存到表中,要显式的执行SQL更新语句才能更新数据,而视图中的数据会随着原表的变化自动更新。

创建视图

格式:

CREATE VIEW 视图名称(<视图列名1>,<视图列名2>,...)
AS
<SELECT语句>

例子:

CREATE VIEW ProductSum (product_type, cnt_product)
AS
SELECT product_type, COUNT(*)
  FROM Product
 GROUP BY product_type;

使用视图

可见,如果使用视图,不用每次都写GROUP BY等一些语句从Product表中取数据。

并且,如果Product表中数据更新,视图也自动更新。

这是因为,视图就是保存好的SELECT语句。

SELECT product_type, cnt_product
  FROM ProductSum;

PostgreSQL数据库创建并使用视图以及子查询

多重视图:以视图为基础创建视图。但是这样会降低SQL性能。

CREATE VIEW ProductSumA (product_type, cnt_product)
AS
SELECT product_type, cnt_product
  FROM ProductSum
 WHERE product_type = '办公用品';

PostgreSQL数据库创建并使用视图以及子查询

定义视图时,不能用ORDER BY子句。因为视图和表,数据行都没有顺序。

(PostgreSQL里面,定义视图时候可以用ORDER BY子句,有些DBMS不行)

视图更新:

如果定义视图的SELECT语句满足一些条件,视图可以被更新。

SELECT子句没用DISTINCT、FROM子句只有一张表、没用GROUP BY、没用HAVING。

通过汇总得到的数据无法更新,这是因为视图和表要同时更新。

如果给上面的ProductSum中添加(‘食物’,3)的数据,原表就需要增加三行种类为食物的数据,但是这些数据我们都不知道,因此没法更新表中的数据。

可以更新下面这样,不通过汇总得到的视图。

CREATE VIEW ProductA (product_id, product_name, product_type, sale_price, purchase_price, regist_date)
AS 
SELECT *
  FROM Product
 WHERE product_type = '办公用品';

向视图插入数据。

INSERT INTO ProductA VALUES ('0009', '铅笔', '办公用品', 95, 10, '2222-10-1');

此时可看到,视图和表都更新了。

PostgreSQL数据库创建并使用视图以及子查询

删除视图:

格式

DROP VIEW 视图名称(<视图列名1>,<视图列名2>,...)

例子

DROP VIEW ProductSum;

然后报错

ERROR:  cannot drop view productsum because other objects depend on it
描述:  view productsuma depends on view productsum
提示:  Use DROP ... CASCADE to drop the dependent objects too.

这是因为前面以ProductSum为基础,创建了一个ProductSumA视图。

可以像下面这样删除ProductSum和与之关联的视图。

DROP VIEW ProductSum CASCADE;

子查询

子查询,相当于一次性视图。

定义视图ProductSum

CREATE VIEW ProductSum (product_type, cnt_product)
AS
SELECT product_type, COUNT(*)
  FROM Product
 GROUP BY product_type;

子查询:将定义视图的SELECT语句直接用到FROM子句里面。

AS ProductSum,ProductSum是子查询的名称。执行完外边的SELECT语句,子查询就消失了。

下面代码,执行顺序,先是FROM子句里面的SELECT语句,然后是外边的SELECT语句。

SELECT product_type, cnt_product
  FROM (SELECT product_type, COUNT(*) AS cnt_product
          FROM Product
         GROUP BY product_type) AS ProductSum;

下面再次查看ProductSum发现,ProductSum已经不存在了。由此看出,子查询是一次性的,并不像视图一样保存到硬盘里面。

PostgreSQL数据库创建并使用视图以及子查询

在子查询的FROM子句里面,可以继续使用子查询。

下面就是把ProductSum里面cnt_product = 4的数据选出来了。

SELECT product_type, cnt_product
  FROM (SELECT *
          FROM (SELECT product_type, COUNT(*) AS cnt_product
                  FROM Product
                 GROUP BY product_type) AS ProductSum
         WHERE cnt_product = 4) AS ProductSum2;

PostgreSQL数据库创建并使用视图以及子查询

标量子查询scalar subquery,返回表中某一行某一列的值(单一值)的子查询。

可以在WHERE子句中使用标量子查询。

由于WHERE子句中无法使用聚合函数,像下面的语句就是错误的。

SELECT product_id, product_name, sale_price
  FROM Product
 WHERE sale_price > AVG(sale_price);

可以通过下面这样去实现。

SELECT product_id, product_name, sale_price FROM Product WHERE sale_price > (SELECT AVG(sale_price) FROM Product);SELECT product_id, product_name, sale_price
  FROM Product
 WHERE sale_price > (SELECT AVG(sale_price)
                         FROM Product);

在任何使用单一值的地方,都可以使用标量子查询。

在SELECT子句中使用标量子查询:

SELECT product_id, product_name, sale_price, (SELECT AVG(sale_price) FROM Product) AS avg_price FROM Product;SELECT product_id, 
       product_name, 
       sale_price,
       (SELECT AVG(sale_price)
          FROM Product) AS avg_price
  FROM Product;

在HAVING子句中使用标量子查询:

不同商品种类的平均销售单价与全部商品的销售单价相比。

SELECT product_type, AVG(sale_price)
  FROM Product
 GROUP BY product_type
HAVING AVG(sale_price) > (SELECT AVG(sale_price)
                              FROM Product);

标量子查询不能返回多行结果,如果返回多行结果,那就是一个普通的子查询,不能用到需要单一输入值的地方了。

关联子查询

现在要选取各个商品种类里面,高于该商品种类平均销售价的商品。

按照商品种类计算平均价格:

SELECT AVG(sale_price)
  FROM Product
 GROUP BY product_type;

因为有三种商品,上面这个查询返回三个结果。

PostgreSQL数据库创建并使用视图以及子查询

那么就不能用下面这种方法了。因为子查询不是标量子查询,不能在WHERE子句里面用。

SELECT product_id, product_name, sale_price
  FROM Product
 WHERE sale_price > (SELECT AVG(sale_price)
                         FROM Product
                        GROUP BY product_type);

在细分的组内进行比较的时候,用到关联子查询。

在子查询里面添加了一个WHERE子句。目的是在同一商品种类中对各商品销售单价和平均单价比较。

由于比较对象是同一个Product表,所以用了P1、P2两个别名。

使用关联子查询,用<表名>.<列名>形式,限定product_type,对平均单价比较。

SELECT product_type, product_name, sale_price
  FROM Product AS P1
 WHERE sale_price > (SELECT AVG(sale_price)
                         FROM Product AS P2
                        WHERE P1.product_type = P2.product_type
                        GROUP BY product_type);

PostgreSQL数据库创建并使用视图以及子查询

而且,不加GROUP BY,也能得到相同结果:

SELECT product_type, product_name, sale_price
  FROM Product AS P1
 WHERE sale_price > (SELECT AVG(sale_price)
                         FROM Product AS P2
                        WHERE P1.product_type = P2.product_type);
PostgreSQL 相关文章推荐
PostgreSQL将数据加载到buffer cache中操作方法
Apr 16 PostgreSQL
Centos环境下Postgresql 安装配置及环境变量配置技巧
May 18 PostgreSQL
postgresql 删除重复数据案例详解
Aug 02 PostgreSQL
关于PostgreSQL JSONB的匹配和交集问题
Sep 14 PostgreSQL
PostGIS的安装与入门使用指南
Jan 18 PostgreSQL
Rust 连接 PostgreSQL 数据库的详细过程
Jan 22 PostgreSQL
Oracle配置dblink访问PostgreSQL的操作方法
Mar 21 PostgreSQL
PostgreSQL事务回卷实战案例详析
Mar 25 PostgreSQL
PostgreSQL并行计算算法及参数强制并行度设置方法
Apr 06 PostgreSQL
postgreSQL数据库基础知识介绍
Apr 12 PostgreSQL
PostgreSQL基于pgrouting的路径规划处理方法
Apr 18 PostgreSQL
postgresql之greenplum字符串去重拼接方式
May 08 PostgreSQL
PostgreSQL并行计算算法及参数强制并行度设置方法
Apr 07 #PostgreSQL
PostgreSQL并行计算算法及参数强制并行度设置方法
Apr 06 #PostgreSQL
PostgreSQL事务回卷实战案例详析
Mar 25 #PostgreSQL
Oracle配置dblink访问PostgreSQL的操作方法
Rust 连接 PostgreSQL 数据库的详细过程
Jan 22 #PostgreSQL
使用PostGIS完成两点间的河流轨迹及流经长度的计算(推荐)
PostGIS的安装与入门使用指南
You might like
提升PHP执行速度全攻略(上)
2006/10/09 PHP
PHP 组件化编程技巧
2009/06/06 PHP
PHP反射机制原理与用法详解
2017/02/15 PHP
php中输出json对象的值(实现方法)
2018/03/07 PHP
php app支付宝回调(异步通知)详解
2018/07/25 PHP
CodeIgniter框架钩子机制实现方法【hooks类】
2018/08/21 PHP
window.open被浏览器拦截后的自定义提示效果代码
2007/11/19 Javascript
顶部缓冲下拉菜单导航特效的JS代码
2013/08/27 Javascript
让网页跳转到指定位置的jquery代码非书签
2013/09/06 Javascript
微信小程序 实战小程序实例
2016/10/08 Javascript
AngularJS实现与Java Web服务器交互操作示例【附demo源码下载】
2016/11/02 Javascript
Bootstrap基本布局实现方法详解
2016/11/25 Javascript
jQuery EasyUI Draggable拖动组件
2017/03/01 Javascript
使用vue.js写一个tab选项卡效果
2017/03/25 Javascript
Angularjs使用指令做表单校验的方法
2017/03/31 Javascript
vue3.0 CLI - 2.5 - 了解组件的三维
2018/09/14 Javascript
解决vue elementUI中table里数字、字母、中文混合排序问题
2020/01/07 Javascript
vue从零实现一个消息通知组件的方法详解
2020/03/16 Javascript
vue实现两个区域滚动条同步滚动
2020/12/13 Vue.js
Python map和reduce函数用法示例
2015/02/26 Python
python3+PyQt5实现支持多线程的页面索引器应用程序
2018/04/20 Python
Python安装lz4-0.10.1遇到的坑
2018/05/20 Python
浅谈Pandas 排序之后索引的问题
2018/06/07 Python
HTML5的结构和语义(5):内嵌媒体
2008/10/17 HTML / CSS
医学生自我鉴定范文
2013/11/08 职场文书
群众路线教育实践活动方案
2014/02/02 职场文书
化学教育专业求职信
2014/07/08 职场文书
村干部四风问题整改措施
2014/09/30 职场文书
承兑汇票转让证明怎么写?
2014/11/30 职场文书
师德师风学习材料
2014/12/19 职场文书
护士年终考核评语
2014/12/31 职场文书
《小蝌蚪找妈妈》教学反思
2016/02/23 职场文书
毕业生自我鉴定范文
2019/05/13 职场文书
致毕业季:你如何做好自己的职业生涯规划书?
2019/07/01 职场文书
有关信念的名言语录集锦
2019/12/06 职场文书
vue项目如何打包之项目打包优化(让打包的js文件变小)
2022/04/30 Vue.js