datawhale9月组队学习task03复杂查询
Posted 临风而眠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了datawhale9月组队学习task03复杂查询相关的知识,希望对你有一定的参考价值。
datawhale9月组队学习task03复杂查询
preparation
一.视图
1.何为视图
- 视图是可视化的表
- 是虚拟的表
- 视图依据SELECT语句来创建
- 操作视图时会根据创建视图的SELECT语句生成一张虚拟表,再在这张虚拟表上做SQL操作
2.视图 VS 表
-
视图没有保存实际的数据 表中保存的是实际数据
视图中保存的是SELECT语句
-
视图不是表,视图是虚表,视图依赖于表
用户可以直接操作基本表,在磁盘中存储是在数据文件中的
但作为用户并不需要太关心底层的存储,除了操作表之外还可以操作视图
视图从基本表中取数据,但不真正存放数据
3.Why need 视图
- 可保存频繁使用的SELECT语句,提高效率
- 可使用户看到的数据更清晰
- 可不对外公开数据表全部字段,增加数据保密性
- 只存放视图的定义,不会出现数据冗余
4.How to create 视图
-
基本语法
CREATE VIEW <视图名称>(<列名1>,<列名2>,...) AS <SELECT语句>
- 其中SELECT 语句需要书写在 AS 关键字之后。 SELECT 语句中列的排列顺序和视图中列的排列顺序相同, SELECT 语句中的第 1 列就是视图中的第 1 列, SELECT 语句中的第 2 列就是视图中的第 2 列,以此类推。而且视图的列名是在视图名称之后的列表中定义的
- 注意的是视图名在数据库中需要是唯一的,不能与其他视图和表重名
CREATE VIEW view_name AS SELECT column_name(s) FROM table_name WHERE condition;
-
视图不仅可以基于真实表,我们也可以在视图的基础上继续创建视图
- 但还是应该尽量避免这种操作。这是因为对多数 DBMS 来说, 多重视图会降低 SQL 的性能
注意
在一般的DBMS中定义视图时不能使用ORDER BY语句
下面这个是错的:
因为视图和表一样,数据行都没有顺序
在 mysql中视图的定义是允许使用 ORDER BY 语句的,但是若从特定视图进行选择,而该视图使用了自己的 ORDER BY 语句,则视图定义中的 ORDER BY 将被忽略
基于单表的视图
CREATE VIEW productsum (product_type, cnt_product)
AS
SELECT product_type, COUNT(*)
FROM product
GROUP BY product_type ;
这时输入
SHOW TABLES;
命令,就会发现多了productsum不过像navicat、datagrip这种还是把视图和表分开的
-
查看视图还是可用SELECT语句
-
或者直接用可视化工具
基于多表的视图
-
先创建一张表
shop_product
CREATE TABLE shop_product (shop_id CHAR(4) NOT NULL, shop_name VARCHAR(200) NOT NULL, product_id CHAR(4) NOT NULL, quantity INTEGER NOT NULL, PRIMARY KEY (shop_id, product_id)); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000A', '东京', '0001', 30); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000A', '东京', '0002', 50); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000A', '东京', '0003', 15); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0002', 30); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0003', 120); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0004', 20); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0006', 10); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0007', 40); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0003', 20); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0004', 50); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0006', 90); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0007', 70); INSERT INTO shop_product (shop_id, shop_name, product_id, quantity) VALUES ('000D', '福冈', '0001', 100);
-
在
product
表和shop_product
表的基础上创建视图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
5.How to alter 视图结构
-
基本语法
ALTER VIEW <视图名> AS <SELECT语句>
- 视图名在数据库中须唯一
- 不可与其他视图和表重名
- 视图名在数据库中须唯一
-
修改前面的那个
productSum
视图ALTER VIEW productSum AS SELECT product_type, sale_price FROM Product WHERE regist_date > '2009-09-11';
-
修改后的视图:
-
6.How to update 视图内容
-
因为视图是一个虚拟表,所以对视图的操作就是对底层基础表的操作,所以在修改时只有满足底层基本表的定义才能成功修改
-
更新视图
上面的productSum视图不包括以上限制条件
UPDATE productsum SET sale_price = '5000' WHERE product_type = '办公用品';
-
查看原表
原表那个也变成5000了!
但是当时的修改语句是
WHERE product_type = '办公用品';
为什么打孔器那个没有变为5000呢?
7.How to delete 视图
-
基本语法
DROP VIEW <视图名1> [ , <视图名2> …]
- 需要相应权限才能成功删除
-
删除
productsum
DROP VIEW productsum;
-
删掉了之后继续操作这个视图就会报错
-
二.子查询
引入
1.What is 子查询
- 将用来定义视图的SELECT语句嵌套在另一个查询语句内部的查询
- 在SELECT子句中先计算子查询,子查询结果作为外层另一个查询的过滤条件,查询可以基于一个表或者多个表
2.子查询与视图的关系
接着上面的引入
- 子查询就是将用来定义视图的 SELECT 语句直接用于 FROM 子句当中。其中AS studentSum可以看作是子查询的名称,而且由于子查询是一次性的,所以子查询不会像视图那样保存在存储介质中, 而是在 SELECT 语句执行之后就消失了
3.嵌套子查询(尽量避免)
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语句不仅会难以理解而且执行效率也会很差,所以要尽量避免这样的使用。
4.标量子查询
-
标量:单一
- 标量子查询:单一子查询
- 所谓的单一是要求我们的SQL语句只能返回一个值
- 即返回表中具体的某一行的某一列
标量子查询有啥用
-
直接看个例子:通过标量子查询语句查询出销售单价高于平均单价的商品
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, (SELECT AVG(sale_price) FROM product) AS avg_price FROM product;
5.关联子查询
-
查询与子查询间存在联系
-
如何建立联系
-
-
查询与子查询的联系
三.各种函数
1.算术函数
先构造一个
samplemath
表格
-- DDL :创建表
USE shop;
DROP TABLE IF EXISTS samplemath;
CREATE TABLE samplemath
(m NUMERIC(10,3),
n INT,
p INT);
-- DML :插入数据
START TRANSACTION; -- 开始事务
INSERT INTO samplemath(m, n, p) VALUES (500, 0, NULL);
INSERT INTO samplemath(m, n, p) VALUES (-180, 0, NULL);
INSERT INTO samplemath(m, n, p) VALUES (NULL, NULL, NULL);
INSERT INTO samplemath(m, n, p) VALUES (NULL, 7, 3);
INSERT INTO samplemath(m, n, p) VALUES (NULL, 5, 2);
INSERT INTO samplemath(m, n, p) VALUES (NULL, 4, NULL);
INSERT INTO samplemath(m, n, p) VALUES (8, NULL, 3);
INSERT INTO samplemath(m, n, p) VALUES (2.27, 1, NULL);
INSERT INTO samplemath(m, n, p) VALUES (5.555,2, NULL);
INSERT INTO samplemath(m, n, p) VALUES (NULL, 1, NULL);
INSERT INTO samplemath(m, n, p) VALUES (8.76, NULL, NULL);
COMMIT; -- 提交事务
-- 查询表内容
-
加减乘除
-
ABS 绝对值
-
MOD 求余数
-
MOD 是计算除法余数(求余)的函数,是 modulo 的缩写。小数没有余数的概念,只能对整数列求余数。
注意:主流的 DBMS 都支持 MOD 函数,只有SQL Server 不支持该函数,其使用
%
符号来计算余数
-
-
ROUND 四舍五入
- 语法:
ROUND( 对象数值,保留小数的位数 )
- 语法:
SELECT m,
ABS(m) AS abscol,
n ,p,
MOD(n,p) AS mod_col,
MOD(n,p) AS mod_col,
ROUND(m,1) AS round_col
FROM samplemath;
2.字符串函数
- 先构造
samplestr
用于学习
-- DDL :创建表
USE shop;
DROP TABLE IF EXISTS samplestr;
CREATE TABLE samplestr
(str1 VARCHAR (40),
str2 VARCHAR (40),
str3 VARCHAR (40)
);
-- DML:插入数据
START TRANSACTION;
INSERT INTO samplestr (str1, str2, str3) VALUES ('opx', 'rt', NULL);
INSERT INTO samplestr (str1, str2, str3) VALUES ('abc', 'def', NULL);
INSERT INTO samplestr (str1, str2, str3) VALUES ('太阳', '月亮', '火星');
INSERT INTO samplestr (str1, str2, str3) VALUES ('aaa', NULL, NULL);
INSERT INTO samplestr (str1, str2, str3) VALUES (NULL, 'xyz', NULL);
INSERT INTO samplestr (str1, str2, str3) VALUES ('@!#$%', NULL, NULL);
INSERT INTO samplestr (str1, str2, str3) VALUES ('ABC', NULL, NULL);
INSERT INTO samplestr (str1, str2, str3) VALUES ('aBC', NULL, NULL);
INSERT INTO samplestr (str1, str2, str3) VALUES ('abc哈哈', 'abc', 'ABC');
INSERT INTO samplestr (str1, str2, str3) VALUES ('abcdefabc', 'abc', 'ABC');
INSERT INTO samplestr (str1, str2, str3) VALUES ('micmic', 'i', 'I');
COMMIT;
-- 确认表中的内容
-
CONCAT 拼接
- CONCAT(str1,str2,str3)
-
LENGTH 字符串长度
- LENGTH(字符串)
-
LOWER 小写转换
- LOWER 函数只能针对英文字母使用,它会将参数中的字符串全都转换为小写。该函数不适用于英文字母以外的场合,不影响原本就是小写的字符。
-
ERPLACE 字符串替换
- REPLACE( 对象字符串,替换前的字符串,替换后的字符串 )
-
SUBSTRING 字符串的截取
- SUBSTRING (对象字符串 FROM 截取的起始位置 FOR 截取的字符数)
-
想试试在datagrip里面搞
- 先选择Query Console
-
然后选择相应的数据库
-
试试!点击绿色按钮执行脚本
SELECT str1, str2, str3, CONCAT(str1,str2,str3) AS str_concat, LENGTH(str1) AS len_str, LOWER(str1) AS low_str, REPLACE(str1,str2,str3) AS rep_str, SUBSTRING(str1 FROM 3 FOR 2) AS sub_str FROM samplestr;
-
跳出result
3.日期函数
-
下面是一些被标准 SQL 承认的可以应用于绝大多数 DBMS 的函数
-
CURRENT_DATE 当前日期
-
CURRENT_TIME 当前时间
-
CURRENT_TIEMSTAMP 当前日期和时间
-
EXTRACT 截取日期元素
-
SELECT CURRENT_TIMESTAMP as now,
EXTRACT(YEAR FROM CURRENT_TIMESTAMP) AS year,
EXTRACT(MONTH FROM CURRENT_TIMESTAMP) AS month,
EXTRACT(DAY FROM CURRENT_TIMESTAMP) AS day,
EXTRACT(HOUR FROM CURRENT_TIMESTAMP) AS hour,
EXTRACT(MINUTE FROM CURRENT_TIMESTAMP) AS MINute,
EXTRACT(SECOND FROM CURRENT_TIMESTAMP) AS second;
4.转换函数
-
CAST 类型转换
-
CAST(转换前的值 AS 想要转换的数据类型)
-
-- 将字符串类型转换为数值类型 SELECT CAST('0001' AS SIGNED INTEGER) AS int_col;
-
-
-
COALESCE 将NULL转换为其他值
-
COALESCE(数据1,数据2,数据3……)
-
COALESCE 是 SQL 特有的函数。该函数会返回可变参数 A 中左侧开始第 1个不是NULL的值。参数个数是可变的,因此可以根据需要无限增加。
在 SQL 语句中将 NULL 转换为其他值时就会用到转换函数。
-
-
SELECT COALESCE(NULL, 11) AS col_1, COALESCE(NULL, 'hello world', NULL) AS col_2, COALESCE(NULL, NULL, '2020-11-01') AS col_3;
-
四.谓词
1.What is 谓词
- 返回值为真值的函数
- 包括TRUE/FALSE/UNKONWN
- 主要谓词
- LIKE
- BETWEEN
- ISN NULL 、 IS NOT NULL
- IN
- EXISTS
2.LIKE谓词 – 用于字符串的部分一致查询
-
部分一致大体可以分为
- 前方一致
- 中间一致
- 后方一致
-
查看之前就导入的表
samplelike
-
前方一致:选出“dddabc”
-
前方一致即作为查询条件的字符串(这里是“ddd”)与查询对象字符串起始部分相同
-
SELECT * FROM samplelike WHERE strcol LIKE 'ddd%';
-
其中的
%
是代表“零个或多个任意字符串”的特殊符号,本例中代表“以ddd开头的所有字符串”
-
-
中间一致:选取出“abcddd”“dddabc”“abdddc”
-
中间一致即查询对象字符串中含有作为查询条件的字符串,无论该字符串出现在对象字符串的最后还是中间都没有关系
-
SELECT * FROM samplelike WHERE strcol LIKE '%ddd%';
-
-
后方一致:选取出“abcddd“
-
后方一致即作为查询条件的字符串(这里是“ddd”)与查询对象字符串的末尾部分相同
SELECT * FROM samplelike WHERE strcol LIKE '%ddd';
-
-
_
下划线匹配任意 1 个字符-
SELECT * FROM samplelike WHERE strcol LIKE 'ab___';
-
总结
综合如上三种类型的查询可以看出,查询条件最宽松,也就是能够取得最多记录的是中间一致
。这是因为它同时包含前方一致和后方一致的查询结果。
3.BETWEEN谓词 – 用于范围查询
-
如选取销售单价100~1000元的商品
SELECT product_name, sale_price FROM product WHERE sale_price BETWEEN 100 AND 1000;
-
注意上面是闭区间
-
若要改为开区间:
-
SELECT product_name, sale_price FROM product WHERE sale_price >100 AND sale_price <1000;
-
4.IS NULL、 IS NOT NULL – 用于判断是否为NULL
SELECT product_name, sale_price
FROM product
WHERE purchase_price IS NULL;
以上是关于datawhale9月组队学习task03复杂查询的主要内容,如果未能解决你的问题,请参考以下文章