SQL复杂一点的查询

  1. 视图的定义
    通过定义视图可以将频繁使用的SELECT语句保存以提高效率。
    通过定义视图可以使用户看到的数据更加清晰。
    通过定义视图可以不对外公开数据表全部字段,增强数据的保密性。
    通过定义视图可以降低数据的冗余。

  2. 创建视图的基本语法

    CREATE VIEW <视图名称>(<列名1>,<列名2>,…) AS <SELECT语句>
    其中SELECT 语句需要书写在 AS 关键字之后。 SELECT 语句中列的排列顺序和视图中列的排列顺序相同, SELECT 语句中的第 1 列就是视图中的第 1 列, SELECT 语句中的第 2 列就是视图中的第 2 列,以此类推。而且视图的列名是在视图名称之后的列表中定义的。
    需要注意的是视图名在数据库中需要是唯一的,不能与其他视图和表重名。

    视图不仅可以基于真实表,我们也可以在视图的基础上继续创建视图。

  3. 修改视图结构的基本语法如下:

    ALTER VIEW <视图名> AS <SELECT语句>
    其中视图名在数据库中需要是唯一的,不能与其他视图和表重名。
    当然也可以通过将当前视图删除然后重新创建的方式达到修改的效果。

  4. 因为视图是一个虚拟表,所以对视图的操作就是对底层基础表的操作,所以在修改时只有满足底层基本表的定义才能成功修改。

    对于一个视图来说,如果包含以下结构的任意一种都是不可以被更新的:

    聚合函数 SUM()、MIN()、MAX()、COUNT() 等。
    DISTINCT 关键字。
    GROUP BY 子句。
    HAVING 子句。
    UNION 或 UNION ALL 运算符。
    FROM 子句中包含多个表。
    视图归根结底还是从表派生出来的,因此,如果原表可以更新,那么 视图中的数据也可以更新。反之亦然,如果视图发生了改变,而原表没有进行相应更新的话,就无法保证数据的一致性了。

  5. 删除视图的基本语法如下:

    DROP VIEW <视图名1> [ , <视图名2> …]
    注意:需要有相应的权限才能成功删除。

  6. 子查询
    我们先来看一个语句(仅做示例,未提供相关数据)

    SELECT stu_name
    FROM (
    SELECT stu_name, COUNT(*) AS stu_cnt
    FROM students_info
    GROUP BY stu_age) AS studentSum;
    这个语句看起来很好理解,其中使用括号括起来的sql语句首先执行,执行成功后再执行外面的sql语句。

  7. 嵌套子查询
    与在视图上再定义视图类似,子查询也没有具体的限制,例如我们可以这样

    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;
    其中最内层的子查询我们将其命名为productSum,这条语句根据product_type分组并查询个数,第二层查询中将个数为4的商品查询出来,最外层查询product_type和cnt_product两列。
    虽然嵌套子查询可以查询出结果,但是随着子查询嵌套的层数的叠加,SQL语句不仅会难以理解而且执行效率也会很差,所以要尽量避免这样的使用。

  8. 标量子查询
    标量就是单一的意思,所谓单一就是要求我们执行的SQL语句只能返回一个值,也就是要返回表中具体的某一行的某一列。

练习题-第一部分
3.1创建出满足下述三个条件的视图(视图名称为 ViewPractice5_1)。使用 product(商品)表作为参照表,假设表中包含初始状态的 8 行数据。

条件 1:销售单价大于等于 1000 日元。
条件 2:登记日期是 2009 年 9 月 20 日。
条件 3:包含商品名称、销售单价和登记日期三列。
对该视图执行 SELECT 语句的结果如下所示。

SELECT * FROM ViewPractice5_1;
执行结果

product_name | sale_price | regist_date
--------------+------------+------------
T恤衫         |   1000    | 2009-09-20
菜刀          |    3000    | 2009-09-20

CREATE VIEW ViewPractice5_1
AS
(SELECT product_name, sale_price, regist_date
FROM (
SELECT * FROM(
SELECT * FROM product
WHERE regist_date=‘2009-09-20’) AS p1
WHERE sale_price >= 1000) AS P2);
3.2向习题一中创建的视图 ViewPractice5_1 中插入如下数据,会得到什么样的结果呢?

INSERT INTO ViewPractice5_1 VALUES (’ 刀子 ', 300, ‘2009-11-02’);
无法插入,因为product_id是主键,不能有空值

3.3请根据如下结果编写 SELECT 语句,其中 sale_price_all 列为全部商品的平均销售单价。

product_id | product_name | product_type | sale_price | sale_price_all
------------+-------------+--------------+------------+---------------------
0001       | T恤衫         | 衣服         | 1000       | 2097.5000000000000000
0002       | 打孔器        | 办公用品      | 500        | 2097.5000000000000000
0003       | 运动T恤       | 衣服          | 4000      | 2097.5000000000000000
0004       | 菜刀          | 厨房用具      | 3000       | 2097.5000000000000000
0005       | 高压锅        | 厨房用具      | 6800       | 2097.5000000000000000
0006       | 叉子          | 厨房用具      | 500        | 2097.5000000000000000
0007       | 擦菜板        | 厨房用具       | 880       | 2097.5000000000000000
0008       | 圆珠笔        | 办公用品       | 100       | 2097.5000000000000000

select product_id, product_name, product_type, sale_price,
(select avg(sale_price) from product) as sale_price_all
from product;
3.4请根据习题一中的条件编写一条 SQL 语句,创建一幅包含如下数据的视图(名称为AvgPriceByType)。

product_id | product_name | product_type | sale_price | avg_sale_price
------------+-------------+--------------+------------+---------------------
0001       | T恤衫         | 衣服         | 1000       |2500.0000000000000000
0002       | 打孔器         | 办公用品     | 500        | 300.0000000000000000
0003       | 运动T恤        | 衣服        | 4000        |2500.0000000000000000
0004       | 菜刀          | 厨房用具      | 3000        |2795.0000000000000000
0005       | 高压锅         | 厨房用具     | 6800        |2795.0000000000000000
0006       | 叉子          | 厨房用具      | 500         |2795.0000000000000000
0007       | 擦菜板         | 厨房用具     | 880         |2795.0000000000000000
0008       | 圆珠笔         | 办公用品     | 100         | 300.0000000000000000

提示:其中的关键是 avg_sale_price 列。与习题三不同,这里需要计算出的 是各商品种类的平均销售单价。这与使用关联子查询所得到的结果相同。 也就是说,该列可以使用关联子查询进行创建。问题就是应该在什么地方使用这个关联子查询。

create view AvgPriceByType as
select p1.product_id, p1.product_name, p1.product_type, p1.sale_price, p2.avg_sale_price
from product as p1,
(select product_type, avg(sale_price) as avg_sale_price from product
group by product_type) as p2
where p1.product_type = p2.product_type;
练习题-第二部分
3.5运算或者函数中含有 NULL 时,结果全都会变为NULL ?(判断题)
是的,因此需要使用coalesce函数

3.6对本章中使用的 product(商品)表执行如下 2 条 SELECT 语句,能够得到什么样的结果呢?
第一条语句能得到除NULL意外的正常的结果
第二条语句查询结果为空

3.7按照销售单价( sale_price)对练习 6.1 中的 product(商品)表中的商品进行如下分类。

低档商品:销售单价在1000日元以下(T恤衫、办公用品、叉子、擦菜板、 圆珠笔)
中档商品:销售单价在1001日元以上3000日元以下(菜刀)
高档商品:销售单价在3001日元以上(运动T恤、高压锅)
请编写出统计上述商品种类中所包含的商品数量的 SELECT 语句,结果如下所示。

SELECT SUM(CASE WHEN sale_price <= 1000 THEN 1 ELSE 0 END) AS ‘低档商品’,
SUM(CASE WHEN sale_price > 1000 AND sale_price <= 3000 THEN 1 ELSE 0 END) AS ‘中档商品’,
SUM(CASE WHEN sale_price > 3000 THEN 1 ELSE 0 END) AS ‘高档商品’
FROM product;

ALTER TABLE Orders_Returns ADD isReturned varchar(5);
UPDATE Orders_Returns set isReturned = (CASE WHEN Return_Reason is null THEN ‘No’ ELSE ‘Yes’ END);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值