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通过oracle_fdw访问Oracle数据的实现步骤
May 21 PostgreSQL
postgresql无序uuid性能测试及对数据库的影响
Jun 11 PostgreSQL
postgresql使用filter进行多维度聚合的解决方法
Jul 16 PostgreSQL
PostgreSQL解析URL的方法
Aug 02 PostgreSQL
PostgreSQL事务回卷实战案例详析
Mar 25 PostgreSQL
PostgreSQL并行计算算法及参数强制并行度设置方法
Apr 06 PostgreSQL
PostgreSQL并行计算算法及参数强制并行度设置方法
Apr 07 PostgreSQL
PostgreSQL基于pgrouting的路径规划处理方法
Apr 18 PostgreSQL
PostgreSQL之连接失败的问题及解决
May 08 PostgreSQL
postgresql中如何执行sql文件
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函数scandir排除特定目录
2014/06/12 PHP
php常用文件操作函数汇总
2014/11/22 PHP
PHP程序员不应该忽略的3点
2015/10/09 PHP
JavaScript 指导方针
2007/04/05 Javascript
基于JQuery的浮动DIV显示提示信息并自动隐藏
2011/02/11 Javascript
JavaScript词法作用域与调用对象深入理解
2012/11/29 Javascript
让AJAX不依赖后端接口实现方案
2012/12/03 Javascript
Javascript查询DBpedia小应用实例学习
2013/03/07 Javascript
jquery js 获取时间差、时间格式具体代码
2013/06/05 Javascript
JavaScript实现生成GUID(全局统一标识符)
2014/09/05 Javascript
用jmSlip编写移动端顶部日历选择控件
2016/10/24 Javascript
JavaScript 基础表单验证示例(纯Js实现)
2017/07/20 Javascript
Angular实现较为复杂的表格过滤,删除功能示例
2017/12/23 Javascript
纯javascript前端实现base64图片下载(兼容IE10+)
2018/09/14 Javascript
vue 进阶之实现父子组件间的传值
2019/04/26 Javascript
VUE 自定义组件模板的方法详解
2019/08/30 Javascript
jquery实现直播弹幕效果
2019/11/28 jQuery
nuxt+axios实现打包后动态修改请求地址的方法
2020/04/22 Javascript
JS实现简易贪吃蛇游戏
2020/08/24 Javascript
[01:04:14]OG vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[59:30]完美世界DOTA2联赛PWL S3 access vs LBZS 第二场 12.20
2020/12/23 DOTA
python实现端口转发器的方法
2015/03/13 Python
Python的Flask框架中Flask-Admin库的简单入门指引
2015/04/07 Python
Python爬取qq music中的音乐url及批量下载
2017/03/23 Python
关于反爬虫的一些简单总结
2017/12/13 Python
详解Python异常处理中的Finally else的功能
2017/12/29 Python
Django bulk_create()、update()与数据库事务的效率对比分析
2020/05/15 Python
python如何处理程序无法打开
2020/06/16 Python
美国网上购买眼镜:Eyeconic
2017/07/29 全球购物
Gerry Weber德国官网:优质女性时装,德国最大的时装公司之一
2019/11/02 全球购物
美国领先的机场停车聚合商:Airport Parking Reservations
2020/02/28 全球购物
仓库管理制度
2014/01/21 职场文书
拾金不昧感谢信
2015/01/21 职场文书
食堂采购员岗位职责
2015/04/03 职场文书
《卧薪尝胆》读后感3篇
2019/12/26 职场文书
Python入门之基础语法详解
2021/05/11 Python