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
PostgreSQL通过oracle_fdw访问Oracle数据的实现步骤
May 21 PostgreSQL
PostgreSQL解析URL的方法
Aug 02 PostgreSQL
PostgreSQL13基于流复制搭建后备服务器的方法
Jan 18 PostgreSQL
PostGIS的安装与入门使用指南
Jan 18 PostgreSQL
Rust 连接 PostgreSQL 数据库的详细过程
Jan 22 PostgreSQL
Oracle配置dblink访问PostgreSQL的操作方法
Mar 21 PostgreSQL
PostgreSQL并行计算算法及参数强制并行度设置方法
Apr 06 PostgreSQL
PostgreSQL数据库创建并使用视图以及子查询
Apr 11 PostgreSQL
PostgreSQL常用字符串分割函数整理汇总
Jul 07 PostgreSQL
PostgreSQL逻辑复制解密原理解析
Sep 23 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中养成7个面向对象的好习惯
2010/07/17 PHP
解析PHP中empty is_null和isset的测试
2013/06/29 PHP
php采用curl实现伪造IP来源的方法
2014/11/21 PHP
PHP对象、模式与实践之高级特性分析
2016/12/08 PHP
PHP中快速生成随机密码的几种方式
2017/04/17 PHP
PHP进阶学习之垃圾回收机制详解
2019/06/18 PHP
PHP实现单文件、多个单文件、多文件上传函数的封装示例
2019/09/02 PHP
javascript一些不错的函数脚本代码
2008/09/10 Javascript
file模式访问网页时iframe高度自适应解决方案
2013/01/16 Javascript
Extjs中通过Tree加载右侧TabPanel具体实现
2013/05/05 Javascript
用JavaScript实现动画效果的方法
2013/07/20 Javascript
js浮点数保留两位小数点示例代码(四舍五入)
2013/12/26 Javascript
移动手机APP手指滑动切换图片特效附源码下载
2015/11/30 Javascript
AngularJS  ng-table插件设置排序
2016/09/21 Javascript
jQuery旋转插件jqueryrotate用法详解
2016/10/13 Javascript
文件上传的几个示例分享【推荐】
2016/12/16 Javascript
jquery实现回车键触发事件(实例讲解)
2017/11/21 jQuery
Puppet的一些技巧
2018/09/17 Javascript
详解 javascript对象创建模式
2020/10/30 Javascript
[45:44]完美世界DOTA2联赛PWL S2 FTD vs PXG 第一场 11.27
2020/12/01 DOTA
Python内置的字符串处理函数详细整理(覆盖日常所用)
2014/08/19 Python
Python3 循环语句(for、while、break、range等)
2017/11/20 Python
python实现求最长回文子串长度
2018/01/22 Python
python os.path.isfile()因参数问题判断错误的解决
2019/11/29 Python
django为Form生成的label标签添加class方式
2020/05/20 Python
python3获取控制台输入的数据的具体实例
2020/08/16 Python
css3截图_动力节点Java学院整理
2017/07/11 HTML / CSS
挪威太阳镜和眼镜网上商城:SmartBuyGlasses挪威
2016/08/20 全球购物
火山咖啡:Volcanica Coffee
2019/10/29 全球购物
香港士多网上超级市场:Ztore
2021/01/09 全球购物
药剂学专业应届生自荐信
2013/09/29 职场文书
HR喜欢的自荐信格式
2013/10/08 职场文书
夜大自我鉴定
2013/10/31 职场文书
文秘专业应届生求职信范文
2013/11/14 职场文书
保险公司客户经理岗位职责
2015/04/09 职场文书
MySQL 5.7常见数据类型
2021/07/15 MySQL