MySQL学习笔记
SQL语句可以分为:
DDL(数据定义语言):包含CREATE、DROP、ALTER
DML(数据操纵语言):SELECT、INSERT、UPDATE、DELETE
DCL(数据控制语言):COMMIT、ROLLBACK、GRANT、REVOKE
SELECT语句基础
基本的SELECT语句:SELECT<列名>……
FROM <表名>;
在SELECT中用*代替列名,可以查询到表中所有数据的信息
当需要删除重复行时,可以使用DISTINCT
SELECT DISTINCT product_type
FROM prodcut;
表的定义的更新:ALTER TABLE语句
变更表名:RENAME TABLE PRODUCT TO product;
向已建的表添加新的列:ALTER TABLE <表名> ADD COLUMN <列的定义>
ALTER TABLE product ADD COLUMN product_pinyin VARCHAR(100);
将已建成的表删除其中某列:ALTER TABLE product DROP COLUMN product_pinyin;
为列设置别名:SELECT product_name AS “商品名称”,
Product_type AS “商品种类”
FROM product;
值得注意的是:在使用AS对列定义中文别名的时候,使用的是双引号。
在WHERE语句下,对数据进行比较筛选
SELECT product_id,product_name,product_type,sale_price
FROM product
WHERE product_price <=1000;
SELECT product_id,product_name,product_type,regist_date
FROM product
WHERE regist_date < ‘2009-9-20’;
值得注意的是:字符串类型的比较是按照字典顺序进行排序的,不能与数字的大小顺序混淆。
比如字符串类型的1 2 3 10 222,按大小排序的话,就是1 10 2 222 3,根据第一个字排序。
SQL语句可以正常地使用加减乘除,如:
SELECT product_id,product_name,product_type,sale_price,
Sale_price*2 as “sale_price x2”
FROM product;
不能使用=、<>等比较符号选出NULL值,当选取值为NULL的记录时,使用专门的IS NULL符号:SELECT product_name,produt_id,product_type,sale_price
FROM product
WHERE sale_price IS NULL;
反之,如果希望选出除NULL以外的记录,则使用 IS NOT NULL
SELECT product_name,produt_id,product_type,sale_price
FROM product
WHERE sale_price IS NOT NULL;
否则,使用=、<>得到的结果为空值
逻辑运算符
NOT的使用
NOT是否定的意思,例如:SELECT product_id,product_name,sale_price
FROM product
WHERE NOT sale_price >=1000;(实际上是<1000)
AND是并的意思,需要多个条件同时成立:
SELECT product_id,product_name,product_type,sale_price
FROM product
WHERE product_type=’衣服’
AND sale_price <3000;
OR表示的是或者的意思,多个中有一项成立即可,使用如AND一致。
相比较而言,AND会比OR有优先执行权,因此在运算中如果想让OR语句先运算,可以使用():
SELECT product_id,product_name,product_type,sale_price,regist_date
FROM product
WHERE product_type=’衣服’
AND (regist_date as ‘2009-09-11’ OR ‘2009-09-20);
这就保证了括号里是先行条件,如果没有括号,会造成:产品类型为衣服,同时是2009-09-11更新的,或者2009-09-20的商品
聚合与排序
对表进行聚合查询
COUNT: 计算表中的记录个数(行数)
SUM: 计算表中数值列中数值的合计值
AVG:计算表中数值列中数值的平均值
MIX:求出表中任意列中数据的最大值
MIN:求出表中任意列中数据的最小值
COUNT 的用法:SELECT COUNT(*)
FROM product;
这里的*称为参数,可以用任一列代替,NULL也会被算进去
返回值为8
如果参数值不是*而是列名,那么数据为NULL的行不会被计算进去;
其他函数不能像COUNT一样将*号作为参数值
SUM 函数的用法与COUNT相差不大:SELECT SUM(sale_price) ,SUM(purchase_price)
FROM product;
此时返回值分别是sale_price和purchase_price两列的合计值
值的注意的是,NULL在SUM计算中是会被无视掉的(但不等于0),因此NULL不会影响SUM的计算。
AVG 的用法和SUM一样:SELECT AVG(sale_price)
FROM product;
值得注意的是,AVG在计算的过程中也是和SUM一样无视掉NULL,因此计算过程中是不包含NULL项的,分母项也不包括NULL。
MAX和MIN 的使用与SUM的用法一样:SELECT MAX(sale_price),MIN(purchase_price)
FROM product;
返回值分别是sale_price和purchase_price两列的最大值和最小值
MAX和MIN与SUM不一样的一点是可以适用于任何数据类型的列,比如日期,对字符串类型的数据也适用。(对汉字的统计是按首个字的首个字母排序大小)
DISTINCT 在聚合函数中的应用: SELECT COUNT(DISTINCT product_type);
FROM product;
需要注意的是,DISTINCT要放在括号内,因为需要先删除重复项,再统计个数。这个函数得到的是商品种类的个数。同理的,其他函数也是同样的用法。
使用 GROUP BY 语句时,SELECT字句中不能出现聚合建以外的列名,但可以有常数(123或者 ‘商品名’)的存在。
GROUP BY 的子句中不能使用列的别名,这与代码的执行顺序是有关的,GROUP BY 先于SELECT子句执行,而列的别名是在SELECT中设定的,因此在执行GROUP BY时,DBMS还不认识别名。
GROUP BY子句的执行结果是无序的,如果要按某种顺序进行排序,需要在SELECT语句中指定。
只有SELECT子句和HAVING子句(以及ORDER BY子句)中能够使用聚合函数,WHERE子句就不能使用。
因为聚合函数不能用在WHERE子句中,因此聚合函数使用条件语句时,用的是HAVING(WHERE子句只能对行进行指定,但不能对组进行指定)
HAVING 函数在要放在GROUP BY函数后面,在SQL语句中的执行顺序是:
FROM—WHERE—GROUP BY—HAVING—SELECT.
HAVING子句和WHERE一样是条件函数,只是它们一个处理的是行,一个是组(WHERE的运行速度比HAVING快。)
例:
SELECT product_type,COUNT(*)
FROM product_type
GROUP BY product_type
HAVING product_type=”衣服”;
HAVING函数中能使用的要素:
1、 常数
2、 聚合函数
3、 GROUP BY中的聚合键
ORDER BY
ORDER BY 子句用来进行数据的排序,放在SELECT函数的末尾(这是因为排序要在准备输出结果时进行。)
SELECT product_id,product_name,product_type,sale_price,
purchase_price,regist_date
FROM product
ORDER BY sale_price;
其中的sale_price列是排序键,在默认情况下,数据是按升序排列。
按降序顺序排列的时候,在ORDER BY 子句中列名后面加上DESC(descendent);
升序则加ASC(ascendent);
指定多个排序键:
在排序的过程中,比如上面例子中的sale_price中500的商品有两个,这时候这两者的先后排序是随机的,因此需要再添加一个排序键进行排序:
SELECT product_id, product_name,product_type,sale_price,
purchase_price,regist_date
FROM product
ORDER BY sale_price,product_id;
原则是先执行左侧的排序键,如果存在同样大小数据的,再执行右侧的排序键。同理的,如果需要也可以再加排序键。
由于不能对NULL使用比较运算符,因此对含有NULL的列进行排序时,NULL行会集中显示在开头或者末尾。
ORDER BY语句可以使用列的别名,这是因为ORDER BY语句是在结果准备输出的时候执行的,此时别名在之前已经在SELECT语句中被执行,因此可以ORDER BY可以认出别名。
ORDER BY中可以使用的列:
可以使用SELECT 子句中未使用的列和聚合函数。
此外,ORDER BY还可以使用列在SELECT语句中的顺序号进行排序(但并不推荐这种用法,未来可能废除):
SELECT product_id,product_name,product_type,sale_price,purchase_price,regist_date
FROM product
ORDER BY sale_price;
SELECT product_id,product_name,product_type,sale_price,purchase_price,regist_date
FROM product
ORDER BY 4;
这两个SELECT语句的执行结果是一样的。
*SELECT语句只是读取数据,不会更改原表中的数据*
数据更新
INSERT语句
通常的INSERT:
INSERT的基本语法:INSERT INTO <表名> (<列名1>,<列名2>,<列名3>,……) VALUES(值1,值2,值3,……);
值得注意的是:插入的值中,字符串类型和日期要用单引号’ ‘。
将列名和值用逗号隔开,分别放在括号内,这种形式称为清单(列清单和值清单),列清单和值清单的列数必须一样,否则会出错。
INSERT INTO ProductIns(product_id,prouduct_name,product_type,
sale_price,purchase_price,regist_date) VALUES('0001','T恤衫',
'衣服',1000,500,'2009-09-20');
对表进行所有列INSERT时,可以省略表名后的列清单,这时VALUES会依次从左到右给每一列赋值:
INSERT INTO ProductIns VALUES('0002','打孔器','办公用品',500,320,'2009-09-11');
多行INSERT
INSERT INTO ProductIns VALUES ('0003','运动T恤','衣服',4000,
2800,NULL),('0004','菜刀','厨房用具',3000,2800,'2009-09-20');
插入NULL
想要对某一列的某个值插入NULL,可以直接在VALUES清单中插入NULL:
INSERT INTO ProductIns VALUES ('0003','运动T恤','衣服',4000,2800,NULL)
但值得注意的是:想要插入NULL的单元格一定不能设置NOT NULL,不然会导致数据插入失败,但在这句错误之前插入的数据并不会受到影响。
插入默认值DEFAULT
在创建表的时候,可以在列的设置里插入DEFAULT约束(比如sale_price 列),这样在对应的列里就会显示默认值。
默认值有显式和隐式两种
1、通过显式方法插入默认值:在VALUES子句中设置DEFAULT关键词
INSERT INTO ProductIns(product_id,prouduct_name,product_type,
sale_price,purchase_price,regist_date) VALUES('0001','T恤衫','衣服',DEFAULT,500,'2009-09-20');
2、通过隐式方法插入默认值:在VALUES子句中不插入DEFAULT(因为建表时已经设置默认值了,因此设置了默认值的列名可以省略):
INSERT INTO ProductIns(product_id,prouduct_name,product_type,
purchase_price,regist_date) VALUES('0001','T恤衫','衣服', 500,'2009-09-20');
在这里要注意的是:如果省略了没有设置默认值的列,那么会自动填充为NULL,但是如果省略的是设置了NOT NULL的列,会出错。
INSERT……SELECT语句可以从其他表中插入数据。这时,SELECT语句下还可以正常地使用WHERE和GROUP BY,但ORDER BY语句是没有任何效果的。
值得注意的是,语句是先执行FROM—WHERE—GROUP BY—HAVING—SELECT—INSERT INTO
插入数据时,是从INSERT中左至右列依次插入的,因此INSERT和SELECT 中的列名可以不一样:
INSERT INTO producttype(product_type,sum_sale_price,sum_purchase_price)
SELECT product_type,SUM(sale_price),SUM(purchase_price)
FROM product
GROUP BY product_type;
*不能用SELECT将一个表的数据插入它本身。*
数据的删除(DELETE)
DROP TABLE会删掉整个表格(删除后需要用CREATE重建表格才能恢复)
DELETE会删除表中的内容,把表留下来。(删除数据后,用INSERT可以重新插入数据)
执行删除命令后,是很难恢复的。
删除表中的数据命令:DELETE FROM product;
在命令行中不能写其他的列名,因为DELETE是按行删除的,不能单独删除某列。
搜索型DELETE
搜索型DELETE是指使用WHERE子句进行有条件的删除。
DELETE FROM product
WHERE sale_price>4000;
DELETE中不能使用GROUP BY 和HAVINNG,只能使用WHERE。
数据的更新UPDATE
当使用INSERT插入数据后,发现有些数据输错了,不用删除表或列,可以用UPDATE进行更新。
UPDATE product
SET regist_date=’2009-09-10’;
指定条件的UPDATE语句:
UPDATE <表名>
SET <列名>=<表达式>
WHERE <条件>;
例如:UPDATE productcopy
SET sale_price=sale_price*10
WHERE product_type="厨房用具";
使用NULL进行更新,直接在SET子句中的表达式输入NULL即可
UPDATE productcopy
SET sale_price=NULL
WHERE product_id=0008
但对于设置了NOT NULL约束的列,会出错。
多列更新
使用多列更新,可以在SET子句中输入多行,用逗号隔开。
UPDATE product
SET sale_price=sale_price*10,
purchase_price=purchase_price/2
WHERE product_type="厨房用具";
关于事务
在执行事务时,只有确认了(COMMIT)才会看到更改之后的数据,ROLLBACK是在执行语句过程中出现问题才起作用的(在出问题的地方前面的语句已经被执行了,因此需要恢复就要用ROLLBACK)。
复杂查询
视图
视图和表的区别就是:是否保存了实际的数据
视图本身不保存数据,只是保存从表中取出数据所用的SELECT语句。
其优势是可以不必存储大量数据占用存储空间以及将频繁使用的SELECT语句保存成视图可以调用。(视图里的数据会随原表的变化自动更新)
创建视图(CREATE VIEW):
CREATE VIEW <视图名>(<视图列名1>,<视图列名2>,……)
AS
SELECT 语句
CREATE VIEW productSum(product_type,cnt_product)
AS
SELECT product_type,COUNT(*)
FROM product
GROUP BY product_type;
SELECT里的列与视图里的列从左至右一一对应。
这里的SELECT语句下的表product也可以是已经建好的视图,但是应该尽量避免在视图上建立视图,因为多重视图会降低SQL的性能。
视图的查询至少需要两个SELECT语句以上,在示例中,一个是执行创建视图的SELECT,另一个是执行查询结果的SELECT: SELECT *FROM productSum;有时候创建的视图很复杂,需要至少两个以上SEELCT.
使用视图的两个限制:
1 不能使用ORDER BY,除此之外的SELECT语句都可以使用
2 对视图进行更新:如果视图中能满足以下条件,就可以使用INSERT、DELETE和UPDATE
(1) SELECT子句中未使用DISTINCT
(2) FROM子句中只有一张表
(3) 未使用GROUP BY 子句
(4) 未使用HAVING子句
在对视图进行更新后,对应的原表也会插入数据。
操作和前面对表的操作一样。
删除视图(DROP VIEW)
删除整个视图:DROP VIEW <视图名称>;
子查询
子查询的作用和视图差不多,都不会储存数据,但有一点不同就是子查询是一次性的,在SELECT语句执行完后就消失了。
子查询是将定义视图的SELECT语句直接用于FROM子句中。
SELECT product_type,cnt_product
FROM(SELECT product_type,COUNT(*) AS cnt_product
FROM product
GROUP BY product_type) AS productSum;
值得注意的是,有时候会存在多个子查询嵌套,这时对每个子查询都应该赋予表名。
子查询会先执行最里面的FROM语句,逐条向外拓展。
关联子查询
当需要在细分的组内进行计算时,使用关联子查询
SELECT continent,name,area FROM world AS P1
WHERE area>=ALL(SELECT area FROM world AS P2
WHERE P2.continent=P1.continent AND area>0);
意思是按continent进行划分。
标量子查询
标量是单一的意思,标量子查询只能返回1行1列的结果。
SELECT *
FROM product
WHERE sale_price>(SELECT AVG(sale_price) FROM product);
这里的SELECT AVG(sale_price) FROM product结果就是单行单列的
能够使用常数、列名的地方都可以使用标量子查询。
函数、谓词、CASE表达式
根据用途,函数可以分为:算术函数、字符串函数、日期函数、转换函数和聚合函数
算术函数:
ROUND函数:
ROUND只能使用NUMERIC类型的数据:(全体位数,小数位数),在创建表格的时候,如果想要让对应列的数据保留小数位,则数据类型应选NUMERIC(全体位数,小数位数),
绝对值——ABS函数
ABS是计算绝对值的函数,正数的绝对值是正数,负数的绝对值是负数。
SELECT m, ABS(m) as abs_m
FROM SampleMath;
在这组SELECT语句中,当m为负值时,abs_m列为正值。
求余——MOD
MOD函数: MOD(被除数,除数)
SELECT n,p,MOD(n,p) AS mod_col
FROM SampleMath;
值得注意的是,小数没有余数的概念,因此MOD求余只能用于数据类型为整数的列。
*SQL Sever不支持该函数
四舍五入——ROUND
ROUND(对象数值,保留小数的位数)
ROUND以小数点为基点,向左为负,向右为正,数值依次增长。比如对象数值为3212.22,保留小数位数为-2,那么输出结果则为3200,如果保留小数位数为1,输出结果则为3212.2
值得注意的是,只有数值为小数的时候,保留小数位数为正数才会起作用。
字符串函数
拼接函数——CONCAT
CONCAT可以将字符串NAHD和KSJD拼接成NAHDKSJD,表达式:CONCAT(<列名1>,<列名2>,……)。
SELECT product_id,product_name,CONCAT(product_id,product_name) as cnd
FROM product;
字符串长度——LENGTH
表达式:LENGTH(字符串)
SELECT product_id,product_name,LENGTH(product_name) as LONG
FROM product;
LENGTH显示的是字符串的长度,值得注意的是,不同的数据库DBMS因为计算字符串长度的单位不一致,会产生不同的结果。
小写转换——LOWER
表达式:LOWER(字符串)
LOWER函数是将大写字母转换成小写字母,因此只适合英文字符串,对于原本就是小写字母和中文字符串没有影响。
SELECT str1, LOWER(str1) as ku
FROM product;
对应的,UPPER是大写转换函数
字符串的替换——REPLACE
表达式:REPLACE(对象字符串,替换前的字符串,替换后的字符串)
比如:字符串为acSASK,现在打算把ac替换为AC,那么ac就是替换前的字符,AC为替换后的字符。
字符串的截取——SUBSTRING
表达式:SUBSTRING(对象字符串 FROM 截取的起始位置 FOR 截取的字符串数)
这里的对象字符串可以是列名,也可以是一个单独的字符串
截取的起始位置从最左侧算起,比如“ASDFGD”字符串,从A至D的位置分别为
123456,现在要从S开始截取,则“截取的起始位置”为2,想要截取到G,则一共有4个字符数,此时“截取的字符串数”为4
日期函数
获得当前日期:CURRENT_DATE;
SELECT CURRENT_DATE;
获得当前时间——CURRENT_TIME
SELECT CURRENT_TIME;
同时获得日期和时间——CURRENT TIMESTAMP
SELECT CURRENT_TIMESTAMP;
截取日期元素——EXTRACT
表达式:EXTRACT(日期元素 FROM 日期)
SELECT CURRENT_TIMESTAMP,
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;
转换函数
类型转换——CAST
CAST(转换前的值 AS 想要转换的数据类型)
例如:SELECT CAST(product_id AS SIGNED INTEGER) AS INT_COL
FROM product;
这里的product-id也可以是某个具体的数值,如’0001’
将字符串转换成日期:
SELECT CAST(product_id AS SIGNED INTEGER) AS INT_COL
FROM product;
COALESCE——将NULL转换成其他值
COALESCE(数据1,数据2,数据3……)
COALESCE函数会返回括号内可变参数中左侧开始第一个不是NULL的值。
SELECT COALESCE(NULL,1) AS COL_1,
COALESCE(NULL,'TEST',NULL) AS COL_2,
COALESCE(NULL,NULL,'2009-11-02') AS COL_3;
谓词
谓词就是判断是否存在满足某种条件的记录,若存在则返回真,若不存在则返回假
判断是否为NULL——IS NULL和IS NOT NULL
选取出某些值为NULL的列的数据,需要使用谓词IS NULL
SELECT product_name,purchase_price
FROM product
WHERE purchase IS NULL;
同理,选取出值不为NULL以外的数据,则用IS NOT NULL
IN谓词——OR的简便用法
使用IN和NOT IN时,是无法选取出NULL数据的
主键可以设置多个:PRIMARY KEY(product_id,shop_id)
这是因为有时候单独的一条主键可能会查出多条数据,因此需要多加一条主键,使主键查询只显示一行数据。
当IN里添加NULL时,返回结果会是NULL,这是很多函数的共性,NULL应该用IS NOT NULL或者IS NULL
使用子句查询作为IN谓词的参数:
——取得大阪店销售的商品的销售单价。
SELECT product_name,sale_price
FROM product
WHERE product_id IN (SELECT product_id
FROM shopproduct
WHERE shop_id =’000C’);
语句执行顺序是:先在shopproduct表中选取出ID为000C的店铺所卖商品的ID,此时IN括号内为('0001’,’0002’,’0003’,’0004’),接着再在product表中选出pproduct_id等于括号内的id的商品信息。
与此相反,NOT IN则表示“除……之外”,与IN相反。
使用查询子句的优势在于,即使数据发生了变更,还可以继续使用同样的SELECT语句,易于维护。
EXIST谓词
EXIST虽然说不等于IN但在很多方面却可以代替IN
SELECT product_name,sale_price
FROM product AS P
WHERE EXIST (SELECT *
FROM shopproduct AS PS
WHERE PS.product_id=p.product);
PS.product_id=p.product.是将两个表关联起来了,这称为关联子查询。同时,NOT EXCEL也可以代替NOT IN
CASE
CASE表达式分简单CASE表达式和搜素CASE表达式两种,其中搜索CASE表达式包含了简单CASE表达式的所有功能,CASE表达式也是函数的一种
表达式:CASE WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
ELSE<表达式>
END
CASE表达式类似于编程语言中的IF函数,先检索第一个WHEN表达式,如果值为真,就会表达式执行THEN语句,如果不为真,则执行下一条WHEN表达式,如果所有的WHEN求值表达式都不为真,则返回ELSE表达式,到这里结束。
CASE最终只会返回一个值,因此就算有时WHEN表达式众多,但返回值只会是一个“1”、“衣服”这样简单的值。
CASE的使用
现在要选出product表中的“衣服”、“办公用品”和“厨房用具”,并 分别在前面添加A、B、C:是结果为A衣服、B办公用品、C厨房用具
SELECT product_name,
CASE WHEN product_type=’衣服’
THEN CONCAT(‘A’,’衣服’)
WHEN product_type=’办公用品’
THEN CONCAT(‘B’,’办公用品’)
WHEN product_type=’厨房用具’
THEN CONCAT(‘C’,’厨房用具’)
ELSE NULL
END AS ABC_product
FROM product;
-- 这里的NULL是说如果WHEN语句不为真,则返回NULL(事实上,就算不写ELSE,默认结果也会是NULL),END后面ABC_product是为CASE输出的结果定一个列名
CASE和其他函数一样,都是在SELECT上实现的。
CASE表达式可以用在任何位置
使用CASE语句将行转换为列
以前学到的GROUP BY是将商品按种类进行汇总,但是得到的是行,并不能得到列
CASE语句可以将行转换成列:
SELECT
SUM(CASE WHEN product_type=’衣服’ THEN sale_pricce ELSE 0 END) AS sum_price_clothes,
SUM(CASE WHEN product_type=’厨房用具’ THEN sale_pricce ELSE 0 END) AS sum_price_kitchen,
SUM(CASE WHEN product_type=’办公用品sale_price ELSE 0 END) AS sum_price_office
FROM product;
当WHEN不满足时,输出0,不为NULL的原因是,后面SUM计算中如果含有NULL,结果会为0.
补充知识:=等号只能对应一个标量子查询,即等号只能对应一个数值,
当子查询中存在多个数值时,可以考虑IN或者对于<>可以使用ALL
SELECT name,continent FROM world WHER population>ALL(SELECT population*3 FROM world as p2 WHERE p2.continent=world.continent and world .name<>p2.name);
对于条件查询中的>ALL,意思是左边的值要全部大于右边的对应的洲的所有值才成立,否则不成立,返回空值。
在这句中,如果不把作比较的值本身从排除出去,那么将没有值符合条件。
集合运算
表的加法——UNION
集合运算符是指加和减
集合运算会除去重复的记录
SELECT……UNION SELECT……,两个SELECT查询出相同的列名。
当两个SELECT 查询语句中列出的列名相同时,重复的数据将会被除去,如果列出的列名不一样,则只是简单地合并。
注意:1、在使用运算符时,作为运算对象的记录的列数必须相同
2、从左侧开始,相同位置上的列必须是同一数据类型,如果一定要合并在一起,可以先用CAST进行数据类型转换。
3、可以使用任何SELECT语句,但ORDER BY子句只能放在最后使用一次。
SELECT product_id, product_name
FROM Product WHERE product_type = '厨房用具'
UNION
SELECT product_id, product_name FROM Product2 WHERE product_type = '厨房用具'
ORDER BY product_id;
想要保留重复的数据,只需在UNION后面添加ALL即可:UNION ALL
这在其他集合运算符中也适用。
选取表中公共部分——INTERSECT
其用法和注意事项和UNION一样,但是MySQL尚不支持该功能
记录的减法(差集)——EXCEPT
减法运算和前面的加法运算UNION的用法和注意事项基本一致,只是减法运算在某些方面与加法 运算不一样,减法运算分被减数和减数,因为被减数和减数的位置不同,得到的结果也不同,就像:12-4和4-12得到的结果是不一样的。
减法运算得到的结果是:被减表 减去 减表中重复的项,被减表中剩余的数据
目前MYSQL也还不支持。
联结(以列为单位对表进行联结)
内联结——INNER JOIN
将另一个表中的列添加到目标表中,值得注意的是,只有两个表都存在同样的联结键的时候,对应的行数据才会显示。比如两个表的联结键是product_id,当目标表中的id为1—8,另一个表的产品id只有1—3和9、10,这时候联结得到的结果就是与1—3的对应的行数据,简而言之,内联结只能选取出同时存在两张表中的数据。
SELECT SP.shop_id, SP.shop_name, SP.product_id, P.product_name, P.sale_price,
IP.inventory_quantity
FROM ShopProduct AS SP INNER JOIN Product AS P
ON SP.product_id = P.product_id
INNER JOIN InventoryProduct AS IP
ON SP.product_id = IP.product_id WHERE IP.inventory_id = 'P001';
内联结最好要给每个表添加别名,同时在SELECT语句中的列名前添加对应的表的别名。(如果来自两个表的列名不一样,可以不加)。
ON 语句是必须的,要放在FROM和WHERE 之间,当需要指定多个联结键时,可以用and或者OR
内联结可以正常使用WHERE GROUP BY ORDER BY等。
外联结——OUTER JOIN
外联结与内联结(INNER JOIN)不一样的是:内联结只能联结两张表中都存在的数据(联结键),而外联结却可以联结两张表中不同时存在的数据(联结键)
比如两个表的联结键是product_id,当主表中的id为1—8,另一个表的产品id只有1—3和9、10,这时候联结得到的结果就是与1—8的product_id对应的行数据,但是完整的数据只有1—3,从另一个表中添加的列,如果没有4—8的数据,就会显示NULL。联结键以主表为主。
外联结与内联结一样使用ON,不同的是在ON前面添加LEFT/RIGHT其中的一个,用来指定主表。
SELECT COALESCE(SP.shop_id, '不明') AS shop_id,
COALESCE(SP.shop_name, '不明') AS shop_name,
P.product_id,
P.product_name,
P.sale_price
FROM ShopProduct SP RIGHT OUTER JOIN Product P
ON SP.product_id = P.product_id
ORDER BY shop_id;
-- 这里的COALESCE是表示如果不是SP.shop_id的值,就填入'不明'
窗口函数与GROUPING
窗口函数就是将表以窗口为单位进行分割,并在其中排序的函数
OLAP----窗口函数
语法:<窗口函数>(参数) OVER (PARTITION BY <列清单> ORDER BY <排序用列清单>)
专用窗口函数可不设置参数
窗口函数的类型主要分为两类——聚合函数和专用窗口函数
聚合函数:
聚合函数类型的窗口函数SUM、AVG,得到的结果是类似于金字塔的数据叠加
SELECT product_name,product_type,sale_price,
SUM(sale_price) OVER (PARTITION BY product_type ORDER BY sale_price) as sum_sale
FROM product;
专用窗口函数
专用窗口函数的类型——RANK、DENSE_RANK和ROU_NUBER,专用窗口函数主要起到排序的作用
RANK: 存在相同的位次,会跳过之后的位次
DENSE_RANK:存在相同的位次,不会跳过之后的位次
ROW_NUMBER: 赋予唯一的位次,不会存在相同的位次
SELECT product_name,product_type,sale_price
RANK() OVER (PARTION BY product_type ORDER BY sale_price) AS rank_sale
FROM product;
再有一个就是窗口函数中的PARTITION BY并不是必须的,PARTITION BY起到分隔整体的作用,与GROUP BY类似(但不会合并行),因此当不用PARTITION BY时,会将整个表格当做一个大窗口计算。
计算移动平均——框架
框架能起到指定一定范围里的数据进行计算
其语法是在ORDER BY子句之后使用指定范围的关键字
例如:SELECT product_name,product_type,sale_price,
AVG(sale_price) OVER (ORDER BY sale_price ROWS 2 PRECEDING) as AVG_sale
FROM product;
PRECEDING是“之前”的意思,此外还有表示“之后”的FOLLOWING,两者可以通过BETWEEN……AND联合使用。
两个ORDER BY
SELECT product_name,product_type,sale_price
RANK() OVER (PARTION BY product_type ORDER BY sale_price) AS rank_sale
FROM product
ORDER BY rank_sale;
之所以设定两个ORDER BY是因为OVER子句里的ORDER BY只起到排序的作用,即给对应的行添加序号,第二个ORDER BY则起到排列的作用。
GROUPING运算符
同时得到合计和小计——ROLLUP
语法上只需要在GROUP BY后面加上WITH ROLLUP即可
如;
SELECT product_type,SUM(sale_price) as SUM_sale
FROM product
GROUP BY product_type WITH ROLLUP;
区分NULL——GROUPING
GROUPING 可以区分原表中的NULL和因ROLLUP合计产生的NULL
SELECT product_type,regist_date,SUM(sale_price),GROUPING(product_type),
GROUPING(regist_date)
FROM product
GROUP BY product_type,regist_date WITH ROLLUP;
当NULL是因超级分组记录所产生的NULL时返回1,其他情况返回0;
MySQL思维导图 https:// pan.baidu.com/s/11Yzjga yd4Q6OMnUBr1V3uQ