(202307)wonderful-sql:复杂一点的查询(task3)

教程链接:Datawhale - 一个热爱学习的社区

知识学习

1 视图

视图是一张虚拟的表。《sql基础教程第2版》用一句话非常凝练的概括了视图与表的区别---"是否保存了实际的数据"。

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

创建视图的基本语法是

sql 复制代码
CREATE VIEW <视图名称>(<列名1>,<列名2>,...) AS <SELECT语句>

注意:可以在视图的基础上再创建视图;需要注意的是在一般的DBMS中定义视图时不能使用ORDER BY语句,因为视图和表一样,数据行都是没有数据的;

我们也可以创建多表视图,使用WHERE进行条件控制

sql 复制代码
CREATE VIEW view_shop_product(product_type, sale_price, shop_name)
AS
SELECT product_type, sale_price, shop_name
  FROM product,
       shop_product
 WHERE product.product_id = shop_product.product_id;

2 子查询

子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从 MySQL 4.1 开始引入,在 SELECT 子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表。

与视图的关系:子查询就是将用来定义视图的 SELECT 语句直接用于 FROM 子句当中。其中AS studentSum可以看作是子查询的名称,而且由于子查询是一次性的,所以子查询不会像视图那样保存在存储介质中, 而是在 SELECT 语句执行之后就消失了。

小结

视图和子查询是数据库操作中较为基础的内容,对于一些复杂的查询需要使用子查询加一些条件语句组合才能得到正确的结果。但是无论如何对于一个SQL语句来说都不应该设计的层数非常深且特别复杂,不仅可读性差而且执行效率也难以保证,所以尽量有简洁的语句来完成需要的功能。

练习题-第一部分

3.1 创建出满足下述三个条件的视图

sql 复制代码
CREATE VIEW ViewPractice5_1 AS
SELECT product_name, sale_price, regist_date
FROM product
WHERE sale_price >= 1000
    AND regist_date = '2009-09-20';

输入 SELECT * FROM ViewPractice5_1; 检查结果

3.2 向习题一中创建的视图 ViewPractice5_1 中插入如下数据,会得到什么样的结果?为什么?

sql 复制代码
INSERT INTO ViewPractice5_1 VALUES (' 刀子 ', 300, '2009-11-02');

结果

sql 复制代码
[2023-07-26 14:18:18] [HY000][1423] Field of view 'shop.ViewPractice5_1' underlying table doesn't have a default value

翻译为底层的表没有默认的值,推测因为这个视图底层的表有的列要求非空,而这里给不出值,就不能了。由此也可知道修改视图也会修改底层的表。

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

sql 复制代码
SELECT product_id, product_name, sale_price, (SELECT AVG(sale_price) FROM product) AS sale_price_avg
FROM product;

3.4 请根据习题一中的条件编写一条 SQL 语句,创建一幅包含如下数据的视图(名称为AvgPriceByType)。

sql 复制代码
CREATE VIEW AvgPriceByType(product_id,product_name,product_type,sale_price,sale_price_avg_type)
AS
SELECT product_id,product_name,product_type,sale_price,
(SELECT avg(sale_price) FROM product AS pm WHERE pm.product_type = pn.product_type GROUP BY product_type) 
    AS sale_price_avg_type FROM product AS pn

练习题-第二部分

3.5 四则运算中含有 NULL 时(不进行特殊处理的情况下),运算结果是否必然会变为NULL ?

是的,四则运算中含有NULL,不进行特殊处理,运算结果是必然变成NULL。

3.6 对本章中使用的 product(商品)表执行如下 2 条 SELECT 语句,能够得到什么样的结果呢

sql 复制代码
SELECT product_name, purchase_price
  FROM product
 WHERE purchase_price NOT IN (500, 2800, 5000);

返回product_name和purchase_price两列,行的数据满足其原本在product表中的purchase_price不是500,2800,500和NULL。

sql 复制代码
SELECT product_name, purchase_price
  FROM product
 WHERE purchase_price NOT IN (500, 2800, 5000, NULL);

NULL不等于任何值,无法判断即使不是500,2800,5000的那些值是否为NULL。

可以用NOT EXISTS字句来查找,因为在子查询中使用等于操作符时,NULL 值将被视为与其他 NULL 值不相等。例如:

sql 复制代码
SELECT * FROM mytable WHERE NOT EXISTS (SELECT * FROM mytable2 WHERE mytable2.col1 = mytable.col1);

3.7 编写语句将商品分为三档

sql 复制代码
SELECT SUM(CASE WHEN sale_price <= 1000 THEN 1 ELSE 0 END) AS low_price,
       SUM(CASE WHEN sale_price BETWEEN 1001 AND 3000 THEN 1 ELSE 0 END ) AS mid_price,
       SUM(CASE WHEN sale_price >= 3001 THEN 1 ELSE 0 END) AS high_price
FROM product;

结果

相关推荐
伏虎山真人19 分钟前
开源数据库 - mysql - mysql-server-8.4(gtid主主同步+ keepalived热切换)部署方案
数据库·mysql·开源
FIN技术铺3 小时前
Redis集群模式之Redis Sentinel vs. Redis Cluster
数据库·redis·sentinel
内核程序员kevin4 小时前
在Linux环境下使用Docker打包和发布.NET程序并配合MySQL部署
linux·mysql·docker·.net
CodingBrother4 小时前
MySQL 中的 `IN`、`EXISTS` 区别与性能分析
数据库·mysql
kayotin4 小时前
Wordpress博客配置2024
linux·mysql·docker
代码小鑫5 小时前
A027-基于Spring Boot的农事管理系统
java·开发语言·数据库·spring boot·后端·毕业设计
小小不董5 小时前
Oracle OCP认证考试考点详解082系列16
linux·运维·服务器·数据库·oracle·dba
甄臻9245 小时前
Windows下mysql数据库备份策略
数据库·mysql
内蒙深海大鲨鱼5 小时前
qt之ui开发
数据库·qt·ui
杀神lwz5 小时前
Java 正则表达式
java·mysql·正则表达式