sql语句进阶教程
转载自:http://blog.csdn.net/u011001084/article/details/51318434
最近从图书馆借了本介绍SQL的书,打算复习一下基本语法,记录一下笔记,整理一下思路,以备日后复习之用。
PS:本文适用SQL Server2008语法。
^1:
| 类型 | 长度 | 说明 |
|---|---|---|
char |
固定长度 | |
nchar |
固定长度 | 处理unicode数据类型(所有的字符使用两个字节表示) |
varchar |
可变长度 | 效率没char高 灵活 |
nvarchar |
可变长度 | 处理unicode数据类型(所有的字符使用两个字节表示) |
- 1字节=8位
- bit就是位,也叫比特位,是计算机表示数据最小的单位。
- byte就是字节,1byte=8bit,1byte就是1B;
- 一个字符=2字节;
MySQL中用重音符`(~)按键。Oracle用双引号。
^2:
1
|
Select -1>选择列,-2>distinct,-3>top
|
1
|
SELECT '直接量' AS `类型`,firstname,lastname
FROM `customers` ;
|

如图,结果中直接量就在一列中了。
Python中的Random包。看来很多时候,一些东西是共通的啊。
StackOverFlow-SQL Server: CASE WHEN OR THEN ELSE END => the OR is not supported
八、布尔逻辑
八、布尔逻辑
关键字:AND/OR/NOT/BETWEEN/IN/IS/NULL
8.1 OR
OR子句意味着,如果确定任意条件为真,那么就该选中该行。
1
|
SELECT userid,name,phone
FROM users
WHERE age<18
OR age>60
|
8.2 使用圆括号
1
|
SELECT CustomerName,
|
本来想要的结果是对来自IL或者CA的客户,同时,只看数量大于8的订单。但是上面执行的结果不是这样的,因为,SQL总是会先处理AND操作符!!!然后才会处理OR操作符。所以,上述语句中,先看到AND并执行如下的条件
1
|
State= 'CA'
|
因此,要用括号来规定顺序:
1
|
SELECT CustomerName,
|
8.3 NOT操作符
NOT操作符表示对后边的内容否定或者取反。
1
|
SELECT CustomerName,State
|
这个其实可以用AND改写的!!!
NOT操作符在逻辑上不是必须的。
8.4 BETWEEN操作符
1
|
SELECT CustomerName,
Sate,
QuantityPurchased
FROM Orders
WHERE QuantityPurchased BETWEEN 8 AND 10
|
8.5 IN操作符
假设你想看到IL或者NY的行:
1
|
SELECT *
|
可以改写成:
1
|
SELECT *
|
8.9 布尔逻辑-IS NULL
为了将某字段NULL值的行或0的行包括进来:
1
|
SELECT *
FROM Products
WHERE weight=0
OR weight IS NULL
|
或者
1
|
SELECT *
FROM Products
WHERE ISNULL(weight,0)=0
|
九、模糊匹配
9.1 LIKE和%搭配
%通配符可以表示任意的字符,它可以表示0个,1个,任意多个字符。
9.2 通配符
除了%以外,还有下划线(_)、方括号起来的characterlist,以及用方括号括起来的脱字符号(^)加上characterlist。
- 下划线表示一个字符
- [characterlist]表示括号中字符的任意一个
- [^characterlist]表示不能是括号中字符的任意一个
例子:1
2
3
4
5SELECT FirstName, LastName FROM Actors WHERE FirstName LIKE '[CM]ARY'
检索以C或者M开头并以ARY结尾的所有行。
9.3 按照读音匹配
SOUNDEX和DIFFERENCE
十、汇总数据
10.1消除重复
使用DISTINCT
1
|
SELECT DISTINCE name,age
FROM users
|
如果age不同,即使name相同,那么这一行就不会被删除重复。
10.2 聚合函数
COUNT\SUM\AVG\MIN\MAX,他们提供了对分组数据进行计数、求和、取平均值、取最小值和最大值等方法。
1
|
SELECT
AVG(Grade) AS 'Average Quiz Score'
MIN(Grade) AS 'Minimum Quiz Score'
FROM Grades
WHERE GradeType='Quiz'
|
COUNT函数可以有3中不同方式使用它。
1.COUNT函数可以用来返回所有选中行的数目,而不管任何特定列的值。
例如:下面语句返回GradeType为’HomeWork’的所有行的数目:
1
|
SELECT
COUNT(*) AS 'Count of Homework Rows'
FROM Grades
WHERE GradeType='HomeWork'
|
这种方式,会计数所有行的个数,即使其中有*NULL。
2.第二种方式指定具体的列
1
|
SELECT
COUNT(Grades) AS 'Count of Homework Rows'
FROM Grades
WHERE GradeType='HomeWork'
|
第一种方式返回3,这一种方式返回2,为什么???因为,这种方式要满足Grades这一列有值,NULL值的行不会计数。
3.使用关键字DISTINCT。
1
|
SELECT
COUNT(DISTINCT FeeType) AS 'Number of Fee Types'
FROM Fees
|
这条语句计数了FeeType列唯一值的个数。
10.3 分组数据-GROUP BY
1
|
SELECT
GradeType AS 'Grade Type',
AVG(Grade)AS 'Average Grade'
FROM Grades
GROUP BY GradeType
ORDER BY GradeType
|
感觉像EXCEL中的分类汇总功能。
如果想把Grade为NULL值的当做0,那么可以用:
1
|
SELECT
GradeType AS 'Grade Type',
AVG(ISNULL(Grade,0))AS 'Average Grade'
FROM Grades
GROUP BY GradeType
ORDER BY GradeType
|
- GROUP BY子句中的列的顺序是没有意义的;
- ORDER BY子句中的列的顺序是有意义的。
10.4 基于聚合查询条件-HAVING
当针对带GROUP BY的一条SELECT语句应用任何查询条件时,人们必须要问查询条件是应用于单独的行还是整个组。
实际上,WHERE子句是单独的执行查询条件。SQL提供了一个名为HAVING的关键字,它允许对组级别使用查询条件。
例子:
查看选修了类型为选修“A”,平均成绩在70分以上的学生姓名,平均成绩。
1
|
SELECT
Name,
AVG(ISNULL(Grades,0)) AS 'Average Grades'
FROM Grades
WHERE GradeType='A'
GROUP BY Name
HAVING AVG(ISNULL(Grades,0))>70
ORDER BY Name
|
修要修类型为A,那么,这是这对行的查询,因此这里要用WHERE。
但是,还要筛选平均成绩,那么,这是一个平均值,建立在聚合函数上的,并不是单独的行,这就需要用到关键字HAVING。需要先将Student分组,然后把查询结果应用到基于全组的一个聚合统计上。
WHERE只保证我们选择了GradeType是A的行,HAVING保证平均成绩至少70分以上。
注意:如果想要在结果中添加GradeType的值,如果直接在SELECT后边添加这个列,将会出错。这是因为,所有列都必须要么出现在GROUP BY中,要么包含在一个聚合函数中。
1
|
SELECT
Name,
GradeType,
AVG(ISNULL(Grades,0)) AS 'Average Grades'
FROM Grades
WHERE GradeType='A'
GROUP BY Name,GradeType
HAVING AVG(ISNULL(Grades,0))>70
ORDER BY Name
|
十一、组合表
11.1 内连接来组合表-Inner Join
通过书中的描述,我感觉内连接更像是用来将主键表、外键表连接起来的工具。
例如:
A表:
| userid | name | age |
|---|---|---|
| 1 | michael | 26 |
| 2 | hhh | 25 |
| 3 | xiang | 20 |
B表:
| orderid | userid | num | price |
|---|---|---|---|
| 1 | 1 | 2 | 3 |
| 2 | 2 | 6 | 6 |
| 3 | 1 | 5 | 5 |
如上表格,那么要连接这两个表格,查询订单1的客户姓名,年龄,订单号:
方式一:
1
|
SELECT name,age,orderid
FROM A,B
WHERE A.userid=B.userid
AND orderid=1
|
方式二,使用现在的内连接实现:
1
|
SELECT name,age,orderid
FROM A
INNER JOIN B
ON A.userid=B.userid
AND orderid=1
|
ON关键字指定两个表如何准确的连接。
内连接中表的顺序:FROM 子句指定了A表,INNER JOIN 子句指定B表,我们调换A,B顺序,所得到的结果相同的!只是显示列的顺序可能会不同而已。
不建议使用方式一的格式。关键字INNER JOIN ON的优点在于显示地表示了连接的逻辑,那是它们唯一的用途。WEHERE的含义不够明显。因为它是条件的意思啊,不是连接的!
11.2 外连接
外连接分为左连接(LEFT OUTER JOIN)、右连接(RIGHT OUTER JOIN)、全连接(FULL OUTER JOIN)。
OUTER是可以省略的。
左连接(LEFT JOIN)
1
|
SELECT name,age,orderid
FROM A
LEFT JOIN B
ON A.userid=B.userid
AND orderid=1
|
外连接的强大之处在于,主表中的数据必然都会保留,从表中列没有值的情况,用NULL补充。
LEFT JOIN 左边的表为主表,右边的表为从表。
11.3 自连接
自连接必然用到表的别名。
1
|
SELECT A.name,B.name as ManagerName
FROM worker as A
LEFT JOIN worker as B
ON A.managerid=B.id
|
11.4 创建视图
1
|
CREATE VIEW ViewName AS
SelectStatement
[WITH CHECK OPTION]
|
视图中不能包含ORDER BY子句。
[WITH CHECK OPTION]表示对视图进行UPDATE,INSERT,DELETE操作时任然保证了视图定义时的条件表达式。
删除视图:
1
|
DROP VIEW ViewName
|
修改视图:
1
|
ALTER VIEW ViewName AS
SelectStatement
|
视图的优点
- 简化用户的操作
- 使用户以多角度看待同一数据
- 对重构数据库提供了一定程度的逻辑独立性
- 对机密数据提供安全保护
十二、补充
12.1 子查询
可以用3种主要的方式来指定子查询,总结如下:
- 当子查询是tablelist的一部分时,它指定了一个数据源。
- 当子查询是condition的一部分时,它成为查询条件的一部分。
- 当子查询是columnlist的一部分时,它创建了一个单个的计算的列。
12.2 索引
索引是一种物理结构,可以为数据库表中任意的列添加索引。
索引的目的是,当SQL语句中包含该列的是偶,可以加速数据的检索。
索引的缺点是,在数据库中,索引需要更多的存储硬盘。另一个负面因素是,索引通常会降低相关的列数据更新速度。这是因为,任何时候插入或者修改一行记录时,索引都必须重新计算该列中的值的正确的排列顺序。
可以对任意的列进行索引,但是只能指定一个列作为主键。指定一个列作为主键意味着两件事情:首先这个列成为了索引,其次保证这列包含唯一的值。
1
|
CREATE INDEX Index2
|
删除一个索引:
1
|
DROP INDX Index2
ON MyTable
|