SQL操作指南四(复杂查询)

2018-11-10  本文已影响0人  了不起的树懒

视图

视图的两大优点
1.由于视图无需保存数据,因此可以节省存储设备的容量;
2.可以将频繁使用的SELECT语句保存成视图,这样就不用每次都书写了(所以应该将常用的SELECT语句做成视图);

视图可以再视图的基础上再次创建视图,如图:



但是,多重视图会降低SQL的性能,因此尽量避免在视图的基础上创建视图。

视图的限制
1.定义视图时不能使用ORDER BY子句:因为视图和表的属性是相同的,即数据行是无序的;
2.对视图进行更新:如果定义视图的SELECT语句能够满足某些条件,那么视图就可以被更新:
①SELECT子句中未使用DISTINCT;
②FROM子句中只有一张表;
③未使用GROUP BY子句;
④未使用HAVING子句;
因为视图和表需要同时进行更新,因此通过聚合得到的视图无法进行更新。

子查询

子查询的特点概括起来就是一张一次性视图,也就是将用以定义视图的SELECT语句直接用于FROM子句当中。
常规视图语法(示例):
CREATE VIEW shop_sum(shop_type,sum_shop)
FROM shop_list
GROUP BY shop_type;

SELECT shop_type,sum_shop
FROM shop_sum;

子查询语法(示例):
SELECT shop_type,sum_shop
FROM (SELECT shop_type,count(*) AS sum_shop FROM shop_list GROUP BY shop_type) AS shop_sum;

两种语法的结果完全相同,子查询作为内层查询会优先执行。
子查询也可以嵌套使用,但是随着子查询的嵌套层数增加,SQL的语句会变得越来越难以读懂,性能也会随之变差,所以我们要尽力避免使用多次嵌套的子查询。

在WHERE子句中使用标量子查询
在WHERE子句中,使用聚合函数是错误的,如:
SELECT shop_id,shop_name,price
FROM shop_list
WHERE price>AVG(price);
虽然在语法上看似满足条件,但是在WHERE子句中不能使用聚合函数,所以这样的SELECT语句是错误的。
那么标量子查询就可以解决这类问题了。首先使用聚合函数AVG求出平均值:
SELECT AVG(price)
FROM shop_list;

再将这段代码直接用到之前错误的代码中:
SELECT shop_id,shop_name,price
FROM shop_list
WHERE price>(SELECT AVG(price) FROM shop_list);
这样就能完整地输出正确的结果。

关联子查询

SELECT shop_id,shop_name,sell_price
FROM shop_list
WHERE sell_price>(SELECT AVG(sell_price) 
    FROM shop_list 
    GROUP BY shop_type);

在学习之前的标量子查询的时候,已经知道在WHERE子句中使用子查询,该子句的查询结果必须是单一的。

使用关联子查询解决方案
只需要在上面的SELECT子句中追加一行,就能输出正确的结果了。

SELECT shop_id,shop_name,sell_price
FROM shop_list AS S1
WHERE sell_price>(SELECT AVG(sell_price) 
    FROM shop_list  AS S2
    WHERE S1.shop_type=S2.shop_type
    GROUP BY shop_type);

这里起到关键作用的是子查询中添加的WHERE子句的条件,该条件的意思是:在同一商品种类中各商品的单价和平均单价进行比较。

SELECT shop_id,shop_name,sell_price
FROM shop_list as S1
WHERE S1.shop_typle=S2.shop_typle 
AND sell_price>(SELECT AVG(sell_price) 
          FROM shop_list AS S2 
          GROUP BY shop_typle);

因为别名S2的作用域在其定义之后,所以在使用”WHERE S1.shop_typle=S2.shop_typle “时S2还未定义,因此产生定义域的错误。

上一篇 下一篇

猜你喜欢

热点阅读