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
PostgreSQL13基于流复制搭建后备服务器的方法
Jan 18 PostgreSQL
使用PostGIS完成两点间的河流轨迹及流经长度的计算(推荐)
Jan 18 PostgreSQL
PostgreSQL并行计算算法及参数强制并行度设置方法
Apr 06 PostgreSQL
PostgreSQL并行计算算法及参数强制并行度设置方法
Apr 07 PostgreSQL
PostgreSQL聚合函数介绍以及分组和排序
Apr 12 PostgreSQL
PostgreSQL出现死锁该如何解决
May 30 PostgreSQL
PostgreSQL之连接失败的问题及解决
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 随机数的产生、页面跳转、件读写、文件重命名、switch语句
2009/08/07 PHP
PHP 函数执行效率的小比较
2010/10/17 PHP
Fine Uploader文件上传组件应用介绍
2013/01/06 PHP
解决form中action属性后面?传递参数 获取不到的问题
2017/07/21 PHP
PHP实现无限极分类的两种方式示例【递归和引用方式】
2019/03/25 PHP
来自chinaz的ajax获取评论代码
2008/05/03 Javascript
查询绑定数据岛的表格中的文本并修改显示方式的js代码
2009/12/15 Javascript
在html页面上拖放移动标签
2010/01/08 Javascript
Jquery AJAX 用于计算点击率(统计)
2010/06/30 Javascript
jquery插件制作 图片走廊 gallery
2012/08/17 Javascript
js实现延迟加载的方法
2015/06/24 Javascript
jQuery实现高亮显示网页关键词的方法
2015/08/07 Javascript
js实现仿网易点击弹出提示同时背景变暗效果
2015/08/13 Javascript
Bootstrap滚动监听(Scrollspy)插件详解
2016/04/26 Javascript
Vue.js中数据绑定的语法教程
2017/06/02 Javascript
javascript按钮禁用和启用的效果实例代码
2017/10/29 Javascript
Vue实现动态创建和删除数据的方法
2018/03/17 Javascript
JavaScript同源策略和跨域访问实例详解
2018/04/03 Javascript
JS实现方形抽奖效果
2018/08/27 Javascript
关于layui表单中按钮自动提交的解决方法
2019/09/09 Javascript
vue实现节点增删改功能
2019/09/26 Javascript
如何利用node.js开发一个生成逐帧动画的小工具
2019/12/01 Javascript
解析Python中的变量、引用、拷贝和作用域的问题
2015/04/07 Python
使用pyqt 实现重复打开多个相同界面
2019/12/13 Python
Python join()函数原理及使用方法
2020/11/14 Python
python抢购软件/插件/脚本附完整源码
2021/03/04 Python
关于CSS Tooltips(鼠标经过时显示)的效果
2013/04/10 HTML / CSS
印尼最大的网上书店:Gramedia.com
2018/09/13 全球购物
美国手机支架公司:PopSockets
2019/11/27 全球购物
应届电子商务毕业自荐书范文
2014/02/11 职场文书
批评与自我批评材料
2014/02/15 职场文书
党员承诺书范文
2014/05/19 职场文书
党员教师一句话承诺
2014/05/30 职场文书
党员教师四风问题对照检查材料
2014/09/26 职场文书
交通事故代理词范文
2015/05/23 职场文书
导游词之杭州西湖
2019/09/19 职场文书