目录
1.查询基础
SELECT语句基础
列的查询
通过 SELECT 语句查询并选取出必要数据的过程称为匹配查询或查询(query)。
--基本的SELECT语句
SELECT <列名>,……
FROM <表名>;
该SELECT 语句包含了SELECT 和FROM 两个子句(clause) 。
SELECT 子句中列举了希望从表中查询出的列的名称,而 FROM 子句 则指定了选取出数据的表的名称。
注:(1)查询多列时,需要使用逗号进行分隔
(2) 查询结果中列的顺序和 SELECT 子句中的顺序相同 。
(3)想要查询出全部列时,可以使用代表所有列的星号(*)不过如果使用星号的话,就无法设定列的显示顺序了 。
为列设定别名
SQL 语句可以使用 AS关键字为列设定别名。
SELECT product_id AS id, product_name AS name, purchase_price AS price
FROM Product;
(1)别名可以使用中文,使用中文时需要用双引号(")括起来 。
注:使用双引号可以设定包含空格 (空白)的别名。但是如果忘记使用双引号就可能出错,因此并不推荐。
大家可以像product_ id这样使用下划线(_)来代替空白。
(2)在SQL语句中使用字符串或者日期常数时,必须使用单引号(')将其括起来。
常数的查询
SELECT 子句中可以书写列名,书写常数,还可以书写表达式(后面有详情)。
过滤表中重复数据
使用DISTINCT过滤product_type列中重复的数据
SELECT DISTINCT product_type
FROM Product;
注:在使用DISTINCT 时,NULL 也被视为一类数据。NULL 存在于多行中时,也会被合并为一条 NULL 数据。
在多列之前使用DISTINCT
SELECT DISTINCT product_type, regist_date
FROM Product;
DISTINCT关键字,作用于多个字段时,需满足多个字段才会过滤重复数据
根据WHERE语句来选择记录
语句通过WHERE 子句来指定查询数据的条件
SELECT语句中的WHERE子句
SELECT <列名>, ……
FROM <表名>
WHERE <条件表达式>;
执行过程:首先通过 WHERE 子句查询出符合指定条件的记录(即:行),然后再选取出SELECT 语句指定的列。
注:
(1)SQL中子句的书写顺序是固定的,不能随意更改。
(2)WHERE子句也可以使用表达式。
注释的书写方法
注释是SQL 语句中用来标识 说明或者注意事项的部分。
写法:
● 1行注释 书写在“--”之后,只能写在同一行。
● 多行注释 书写在“/*”和“*/”之间,可以跨多行。
注释能够帮助阅读者更好地理解SQL 语句,特别是在书写复杂的SQL 语句时, 希望大家能够尽量多加简明易懂的注释。
算术运算符和比较运算符
算术运算符
含义 | 运算符 |
---|---|
加法运算 | + |
减法运算 | - |
乘法运算 | * |
除法运算 | / |
SELECT 子句中书写算术表达式
SELECT product_name, sale_price, sale_price * 2 AS "sale_price_x2"
FROM Product;
SELECT子句中可以使用常数或者表达式。
注:SQL 中也可以像平常的运算表达式那样使用括号( )。括号中 运算表达式的优先级会得到提升,优先进行运算。
需要注意NULL
A 5 + NULL B 10 - NULL
C 1 * NULL D 4 / NULL
E NULL / 9 F NULL / 0
实际上所有包含 NULL 的计算,结果肯定是 NULL,NULL / 0也不例外。
比较运算符
运算符 | 含义 |
---|---|
= | 和~相等 |
<> | 和~不相等 |
>= | 大于等于~ |
> | 大于~ |
<= | 小于等于~ |
< | 小于~ |
--例:选取出销售单价大于等于1000日元的记录
SELECT product_name, product_type, sale_price
FROM Product
WHERE sale_price >= 1000;
注:
(1)小于某个日期就是在该日期之前的意思
(2)使用比较运算符时一定要注意不等号和等号的位置。
WHERE子句的条件表达式中也可以使用计算表达式
--例:
SELECT product_name, sale_price, purchase_price
FROM Product
WHERE sale_price - purchase_price >= 500;
对字符串使用不等号时的注意事项
--例:选取出大于'2'的数据的SELECT语句
SELECT chr
FROM Chars
WHERE chr > '2';
注: 2 和'2' 并 不一样。
chr 列被定为字符串类型,并且在对字符串类型的数据进行大小比较时,使用的是和数字比较不同的规则。
字符串类型的数据比较规则即:以相同字符开头的单词比不同字符开头的单词更相近,与字典顺序类似。
'10' 和'11' 同样都是以'1' 开头的字符串,首先判定为比'2' 小。
不能对NULL使用比较运算符
--例:选取出进货单价不是2800日元的记录
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price <> 2800;
这两条记录由于进货单价 不明(NULL),因此无法判定是不是 2800日元。
--例:错误的SELECT语句(一条记录也取不出来)
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price = NULL;
使用=运算符也还是无法选取出NULL 的记录
SQL 提供了专门用来判断是否为 NULL 的IS NULL 运算符。
--例:选取NULL的记录
SELECT product_name, purchase_price
FROM Product
WHERE purchase_price IS NULL;
反之,希望选取不是NULL 的记录时,需要使用 IS NOT NULL 运 算符
逻辑运算符
NOT运算符
NOT运算符用来否定某一条件,但是不能滥用。
--例:选取出销售单价大于等于1000日元的记录
SELECT product_name, product_type, sale_price
FROM Product
WHERE NOT sale_price < 1000;
--例:结果与上例一致
SELECT product_name, product_type, sale_price
FROM Product
WHERE sale_price >= 1000;
AND运算符和OR运算符
AND 运算符在其两侧的查询条件都成立时整个查询条件才成立,其意思相当于“并且”。
OR 运算符在其两侧的查询条件有一个成立时整个查询条件都成立, 其意思相当于“或者”
注:AND 运算符优先于 OR 运算符,想要优先执行OR运算符时可以使用括号。
--例:在WHERE子句的查询条件中使用OR运算符
SELECT product_name, purchase_price
FROM Product
WHERE product_type = '厨房用具' OR sale_price >= 3000;
通过括号强化处理
--例:通过使用括号让OR运算符先于AND运算符执行
SELECT product_name, product_type, regist_date
FROM Product
WHERE product_type = '办公用品' AND ( regist_date = '2009-09-11' OR regist_date = '2009-09-20');
逻辑运算符和真值
NOT、AND 和 OR 称为逻辑运算符。这里所说的逻辑就是对真值进行操作的意思。
真值就是值为真(TRUE)或假 (FALSE)其中之一的值
AND 运算符两侧的真值都为真时返回真,除此之外都返回假。
OR 运算符两侧的真值只要有一个不为假就返回真,只有当其两侧的真值都为假时才返回假。
NOT 运算符只是单纯的将真转换为假,将假转换为真。
含有NULL时的真值
既不是真也不是假,这时真值是除真假之外的第三种值——不确定(UNKNOWN)
与通常的逻辑运算被称为二值逻辑相对,只有 SQL 中 的逻辑运算被称为三值逻辑。
考虑到使用NULL 时的条件判断会变得异常复杂。因此,数据库领域的有识之士们达成了“尽量不使用 NULL”的共识。
2.聚合与排序
(1)对表进行聚合查询
通过 SQL 对数据进行某种操作或计算时需要使用函数
5个常用的函数:
COUNT: 计算表中的记录数(行数)
SUM: 计算表中数值列中数据的合计值
AVG: 计算表中数值列中数据的平均值
MAX: 求出表中任意列中数据的最大值
MIN: 求出表中任意列中数据的最小值
用于汇总的函数称为聚合函数或者聚集函数。
所谓聚合,就是将多行汇总为一行。实际上,所有的聚合函数都是这样,输入多行输出一行。
计算表中数据的行数(COUNT)
用COUNT 函数时,输入表的列,就能够输出数据行数。
--语法:
SELECT COUNT(parameter)
FROM 表名;
--计算全部数据的行数
SELECT COUNT(*)
FROM Product;
--计算NULL之外的数据行数
SELECT COUNT(具体字段名)
FROM Product;
COUNT函数的结果根据参数的不同而不同。如:COUNT(*)会得到包含NULL的数据的行数,而COUNT(<列名>)会得到NULL之外的数据行数。
注: COUNT 函数使用*代替所有列,其他函数并不能将星号作为参数。
计算合计值(SUM)
语法与COUNT函数基本相同
聚合函数会将NULL排除在外。但COUNT(*)例外,并不会排除NULL。
--计算分别slae_price与purchase_price的合值
SELECT SUM(sale_price), SUM(purchase_price)
FROM Product;
注:所有的聚合函数,如果以列名为参数,那么在计算之前就已经把 NULL 排除在外了。因此,无论有多少个 NULL 都会被无视。这与“等 价为 0”并不相同 。
计算平均值
其语法和 SUM函数完全相同
不会计算值为的NULL行
--计算sale_price列的平均值
SELECT AVG(sale_price)
FROM Product;
计算最大值和最小值(MAX&MIN)
这两个函数的语法与 SUM 的语法相同
但是,MAX/MIN 函数和SUM/AVG函数有一点不同,那就是 SUM/ AVG函数只能对数值类型的列使用,而 MAX/MIN 函数原则上可以适用 于任何数据类型(能够排序)的列。
使用聚合函数过滤重复值(DISTINCT)
--计算去除重复数据后的数据行数
SELECT COUNT(DISTINCT product_type)
FROM Product;
--先计算数据行数再删除重复数据的结果
SELECT DISTINCT COUNT(product_type)
FROM Product;
--两者结果不一致
对表进行分组
GROUP BY子句
--语法
SELECT <列名1>, <列名2>, <列名3>, ……
FROM <表名>
GROUP BY <列名1>, <列名2>, <列名3>, ……;
GROUP BY 子句就像切蛋糕那样将表进行分组
在 GROUP BY 子句中指定的列称为聚合键或者分组列。
子句的书写顺序(暂定) 1. SELECT → 2. FROM → 3. WHERE → 4. GROUP BY
聚合键中包含NULL的情况
--按照进货单价统计数据行数
SELECT purchase_price, COUNT(*)
FROM Product
GROUP BY purchase_price;
聚合键中包含NULL时,在结果中会以“不确定”行(空行)的形式表现出来。
使用WHERE子句时GROUP BY的执行结果
-- 语法:使用WHERE子句和GROUP BY子句进行汇总处理
SELECT <列名1>, <列名2>, <列名3>, ……
FROM <表名>
WHERE
GROUP BY <列名1>, <列名2>, <列名3>, ……;
执行顺序:会先根据 WHERE 子句指定的条件进行过滤,然后再进行汇总处理。
即:GROUP BY 和 WHERE 并用时 SELECT 语句的执行顺序 FROM → WHERE → GROUP BY → SELECT
--例:
SELECT purchase_price, COUNT(*)
FROM Product
WHERE product_type = '衣服'
GROUP BY purchase_price;
与聚合函数和GROUP BY子句有关的常见错误
1.把聚合键之外的列名书写在SELECT 子句之中。(只有MySQL认同这种语法)
聚合键相对应的、同时存在多个值的列出现在SELECT 子 句中的情况,理论上是不可能的。
使用GROUP BY子句时,SELECT子句中不能出现聚合键之外的列名。
2.在GROUP BY子句中写了列的别名
--错误示范
SELECT product_type AS pt, COUNT(*)
FROM Product
GROUP BY pt;
--原因:由SQL语句在DBMS内部的执行顺序造成的
在GROUP BY子句中不能使用SELECT子句中定义的别名。
3.GROUP BY子句的结果能排序吗
GROUP BY子句结果的默认显示是无序的。
4.在WHERE子句中使用聚合函数
只有 SELECT 子句和 HAVING 子句( ORDER BY 子句)中能够使用COUNT 等聚合函数。
为聚合结果指定条件
HAVING子句
由于WHERE 子句只能指定记录(行)的条件,而不能用来指定组的条件,所以可以使用HAVING子句。
--语法:
SELECT <列名1>, <列名2>, <列名3>, ……
FROM <表名>
GROUP BY <列名1>, <列名2>, <列名3>, ……
HAVING <分组结果对应的条件>
--注:HAVING子句要写在GROUP BY子句之后。
使用 HAVING 子句时 SELECT 语句书写顺序 SELECT → FROM → WHERE → GROUP BY → HAVING
-- 例1:从按照商品种类进行分组后的结果中,取出“包含的数据行数为2 行”的组
SELECT product_type, COUNT(*)
FROM Product
GROUP BY product_type
HAVING COUNT(*) = 2;
--例2:使用HAVING子句设定条件的情况
SELECT product_type, AVG(sale_price)
FROM Product
GROUP BY product_type
HAVING AVG(sale_price) >= 2500;
HAVING 子句中 能够使用的3种要素如下所示:
● 常数
● 聚合函数
● GROUP BY子句中指定的列名(即聚合键)
WHERE子句与HAVING子句
WHERE 子句 = 指定行所对应的条件
HAVING 子句 = 指定组所对应的条件
对查询结果进行排序
ORDER BY子句
通过在 SELECT 语句末尾添加 ORDER BY 子句来明确指定排列顺序。
--语法:
SELECT <列名1>, <列名2>, <列名3>, ……
FROM <表名>
ORDER BY <排序基准列1>, <排序基准列2>, ……
--ORDER BY子句中书写的列名称为排序键。
子句的书写顺序
1. SELECT 子句 → 2. FROM 子句 → 3. WHERE 子句 → 4. GROUP BY 子句 → 5. HAVING 子句 → 6. ORDER BY 子句注:不论何种情况,ORDER BY 子句都需要写在 SELECT 语句的末尾。
指定升序或降序
在OPDER BY子句的列名后面使用 DESC(降序)ASC(默认升序) 关键字。
--按照销售单价由高到低(降序)进行排列
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY sale_price DESC;
注:由于 ASC 和 DESC 这两个关键字是以列为单位指定的,因此可以 同时指定一个列为升序,指定其他列为降序。
指定多个排序键
如果想要对该顺序的商品进行更细致的排序的话,就需要再添加一个 排序键。
--按照销售单价和商品编号的升序进行排序
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY sale_price, product_id;
规则是优先使用左侧的键,如果该列存在相同值的话,再接着参考右侧的键。当然,也可以同时使用 3个以上的排序键。
NULL的顺序
使用含有 NULL 的列作为排序键时, NULL 会在结果的开头或末尾汇总显示,因为NULL值可以被认为是最小值。
--按照进货单价的升序进行排列
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY purchase_price;
在排序键中使用显示用的别名
在 GROUP BY子句中不能使用 SELECT子句中定义的别名,但是在 ORDER BY子句中却是允许使用名的。
--ORDER BY子句中可以使用列的别名
SELECT product_id AS id, product_name, sale_price AS sp, purchase� _price
ROM Product
ORDER BY sp, id;
使用 HAVING 子句时 SELECT 语句的顺序
FROM→WHERE→GROUP BY→HAVING→SELECT→ORDER BY
ORDER BY子句中可以使用的列
ORDER BY 子句中也可以使用存在于表中、但并不包含在 SELECT 子句之中的列
--例:SELECT子句中未包含的列也可以在ORDER BY子句中使用
SELECT product_name, sale_price, purchase_price
FROM Product
ORDER BY product_id;
ORDER BY子句中可以使用列的编号 (不推荐)
-- 通过列名指定
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY sale_price DESC, product_id;
-- 通过列编号指定
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY 3 DESC, 1;