相关文章推荐
大力的松鼠  ·  Mysql比较日期和时间 - ·  1 月前    · 
豪情万千的上铺  ·  mysql ...·  1 月前    · 
奔跑的骆驼  ·  TiDB 2.1.17 Release ...·  2 月前    · 
文雅的莴苣  ·  【RecyclerView】 ...·  1 年前    · 
讲道义的毛豆  ·  ASP.NET ...·  1 年前    · 
MySQL学习笔记

MySQL学习笔记

4 年前

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思维导图 pan.baidu.com/s/11Yzjga

发布于 2018-11-01 19:24