《SQL基础教程》学习笔记Ch5

5复杂查询

5-1视图

视图和表

当我们创建表时,会通过INSERT语句将数据保存到数据库中,而数据库中的数据会被保存到计算机的存储设备中;但是使用视图不会将数据保存在数据库中,实际上视图只保存SELECT语句,从视图中读取数据时,视图会在内部执行该SELECT语句并创建出一张临时表。

视图的优点:
1.无需保存数据,节省存储设备的容量
2.可以将频繁使用的SELECT语句保存为视图

创建视图的方法
--创建ProductSum视图
CREATE VIEW ProductSum (product_type, cnt_product) --视图的列名
AS
SELECT product_type, COUNT(*)
  FROM Product
 GROUP BY product_type;
--使用视图
SELECT product_type, cnt_product
  FROM ProductSum;
5-1.png

在FROM子句中使用视图的查询通常有两个步骤:
1.首先执行定义视图的SELECT子句;
2.根据得到的结果,再执行在FROM子句中使用视图的SELECT子句

定义视图时,可以使用WHERE,GROUP BY,HAVING等语句
此外应该避免下列的多重视图(以视图的基础创建视图):

CREATE VIEW ProductSumJim (product_type, cnt_product)
AS
SELECT product_type, cnt_product
  FROM ProductSum
 WHERE product_type = '办公用品';
视图的限制

1.定义视图时不能使用ORDER BY子句
这是因为视图和表一样,数据行是没有顺序的
2.只在某些条件下可以进行更新
更新语句:INSERT,DELETE,UPDATE

比较有代表性的条件:
SELECT子句未使用DISTINCT;
FROM子句中只有一张表;
未使用GROUP BY子句;
未使用HAVING子句。

视图和表需要同时进行更新,因而通过汇总(GROUP BY)得到的视图无法进行更新。

--能够进行更新的视图
CREATE VIEW ProductJim (product_id, product_name, product_type, sale_price, purchase_price, regist_date)
AS
SELECT *
  FROM Product
 WHERE product_type = '办公用品';
--向视图中添加数据行
INSERT INTO ProductJim VALUES ('0009', '印章', '办公用品', 95, 10, '2009-11-30');

另外,需要注意的是,在PostgreSQL运行上面的插入语句会报错,由于PostgreSQL初始设定视图为只读,我们通过下列语句来允许PostgreSQL对视图进行更新:

CREATE OR REPLACE RULE insert_rule
AS ON INSERT 
TO  ProductJim DO INSTEAD
INSERT INTO Product VALUES(
    new.product_id,
    new.product_name,
    new.product_type,
    new.sale_price,
    new.purchase_price,
    new.regist_date);

执行的结果:视图及原表中数据均已被插入

删除视图
DROP VIEW ProductSum;

在PostgreSQL中此句会出错,由于关联视图存在的原因,修改为:

DROP VIEW ProductSum CASCADE;

5-2子查询

首先来复习一下前面是怎么使用视图来查询的:

--创建ProductSum视图
CREATE VIEW ProductSum (product_type, cnt_product) --视图的列名
AS
SELECT product_type, COUNT(*)
  FROM Product
 GROUP BY product_type;
--使用视图
SELECT product_type, cnt_product
  FROM ProductSum;

所谓子查询:

-- 在FROM子句中直接书写定义视图的SELECT语句
SELECT product_type, cnt_product
  FROM (SELECT product_type, COUNT(*) AS cnt_product
         FROM Product
         GROUP BY product_type) AS ProductSum;

这两种方式得到的结果完全一致。
执行顺序是先执行括号内的SELECT语句,再执行括号外的SELECT语句。

--尝试增加子查询的层数
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;
5-2.png
子查询的名称

原则上,子查询必须使用AS设定名称

标量子查询

标量子查询指的是必须且只能返回1行1列的子查询
假设我们想要“查询出销售单价高于平均销售单价的商品”

--错误的语句
--在WHERE子句中不能使用聚合函数
SELECT product_id, product_name, sale_price
  FROM Product
 WHERE sale_price > AVG(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);
5-3.png
标量子查询的书写位置

能够使用常数或者列名的地方,无论是SELECT子句、GROUP BY子句、HAVING子句还是ORDER BY子句,几乎所有的地方都可以使用

--在SELECT子句中使用标量子查询
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子句中使用
SELECT product_id, 
       product_name,
       sale_price,
       (SELECT AVG(sale_price)
         FROM Product
         GROUP BY product_type) AS avg_price
  FROM Product;

该段会报错,这是由于子查询的结果是三个而不是一个,不再是标量子查询,不可以写在SELECT子句中

5-3关联子查询

普通的子查询和关联子查询的区别

假设这次我们想要“查询出某个商品类中高于此类商品平均销售单价的商品”

--按照商品种类计算平均价格
SELECT AVG(sale_price)
  FROM Product
 GROUP BY product_type;
--发生错误的子查询
SELECT product_id, product_name, sale_price
  FROM Product
 WHERE sale_price > (SELECT AVG(sale_price)
                       FROM Product
                    GROUP BY 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);
5-4.png

在这里起到关键作用的是在子查询中添加的WHERE子句的条件,它的意思是在同一商品种类中,对商品的销售单价和平均单价进行比较。
由于作为比较对象的都是同一张Product表,因此要使用P1和P2两个别名。
需要注意的是:
1.关联子查询也是用来对集合进行切分的
2.结合条件一定要写在子查询中

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容

  • 鼓浪屿岛上的手工茶饼坊里,我让逗比帮我拍下这张照片,这是这次厦门之旅我最喜欢的一张照片。 逗比说,帮你拍了那么多张...
    影秋千阅读 278评论 2 1
  • 不得不安利最近大火的电视剧《微微一笑很倾城》。 什么,你们都说杨洋在里面很高冷?不不不不,我不觉得高冷。这才是一个...
    晚来Yvonne阅读 1,798评论 3 12
  • 一幅简单的缠绕画,缠绕的有点不规整 今天就当偷偷懒吧~ 超级简单十分钟搞定, 喜欢就动起手来了~
    小梅绘生活阅读 581评论 4 5
  • 幸福帮第九期“如何提升孩子的学习兴趣”微课堂语音整理。 本次微课老师将从以下几点,为大家分享自己关于提升孩子的学习...
    幸福帮阅读 320评论 0 0