1.1检索所有行和列
问题:你有一张表,并且想查看表中的所有数据。
解决方案1:
select * from EMP
解决方案2:
select empno,ename,job,sal,mgr,hiredate comm,deptno from EMP
说明:
建议使用方案2,因为别人看你的代码的时候不一定知道你查询的表里面的列,所以还是写出查询的具体列更方便阅读。其次从优化的角度来说,尽量避免“ select * ” 的存在,使用具体的列代替*,避免返回多余的列。
【技巧】
- 查看SQL语句执行时间:
set statistics time on
select * from EMP
-- 注释:这里写你要测试执行时间的SQL语句
set statistics time off
运行结束之后,从消息栏,可以查看
SQL Server 执行时间:
CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。
- 查看SQL语句查询时对I/0的操作情况
set statistics io on
select * from EMP
-- 注释:这里写你要测试的SQL语句
set statistics io of
运行结束之后,从消息栏,可以查看:
表 'EMP'。扫描计数 1,逻辑读取 1 次,物理读取 0 次,
预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
1.2筛选行
问题:你有一张表,并且只想查看满足指定条件的行。
解决方案:
使用 WHERE 子句指明保留哪些行。使用 WHERE 子句来筛选出我们感兴趣的行。如果 WHERE 子句的表达式针对某一行的判定结果为真,那么就会返回该行的数据。
例如,下面的语句将查找部门编号为 10 的所有员工。
select * from EMP where DEPNO=10;
结果:
EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
---|---|---|---|---|---|---|---|
7782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00.000 | 2450 | NULL | 10 |
7839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00.000 | 5000 | NULL | 10 |
7934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00.000 | 1300 | NULL | 10 |
1.3查找满足多个查询条件的行
问题:你想返回满足多个查询条件的行。
解决方案:
使用带有 OR 和 AND 和圆括号()的 WHERE 子句。
例如,如果你想找出部门编号为 10 的所有员工、有奖金的所有员工以及部门编号是 20 且工资低于 2000 美元的所有员工。
【分析】也就是要找满足以下三种情况之一的员工(注意不是要求同时满足)
- 部门编号=10;
- 奖金不为Null(注意不是:奖金!=0,因为我们在数据库中,对无奖金的,填写为NULL);
- 部门编号=20 & 工资<=2000;
select * from EMP
where DEPTNO=10
or COMM not NULL
or SAL<=2000 and DEPTNO=20;
结果:
EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
---|---|---|---|---|---|---|---|
7369 | SMITH | CLERK | 7902 | 1980-12-17 00:00:00.000 | 800 | NULL | 20 |
7499 | ALLEN | SALESMAN | 7698 | 1981-02-20 00:00:00.000 | 1600 | 300 | 30 |
7521 | WARD | SALESMAN | 7698 | 1981-02-22 00:00:00.000 | 1250 | 500 | 30 |
7654 | MARTIN | SALESMAN | 7698 | 1981-09-28 00:00:00.000 | 1250 | 1400 | 30 |
7782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00.000 | 2450 | NULL | 10 |
7839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00.000 | 5000 | NULL | 10 |
7844 | TURNER | SALESMAN | 7698 | 1981-09-08 00:00:00.000 | 1500 | 0 | 30 |
7876 | ADAMS | CLERK | 7788 | 1983-01-12 00:00:00.000 | 1100 | NULL | 20 |
7934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00.000 | 1300 | NULL | 10 |
【补充】检索:20号部门中有奖金的员工和工资不高于2000的员工
SQL语句:
select * from EMP
where (
or comm is not null
or sal <= 2000
)
and deptno=20;
【分析】以上SQL语句中的where字句的逻辑运算就是
(a|b)&c=(a&c)|(b&c)
where (comm is not null and deptno=20) or (sal <= 2000 and deptno=20)
结果:
EMPNO | ENAME | JOB | MGR | HIREDATE | SAL | COMM | DEPTNO |
---|---|---|---|---|---|---|---|
7369 | SMITH | CLERK | 7902 | 1980-12-17 00:00:00.000 | 800 | NULL | 20 |
7876 | ADAMS | CLERK | 7788 | 1983-01-12 00:00:00.000 | 1100 | NULL | 20 |
1.4筛选列
问题:你有一张表,并且只想查看特定列的值。
解决方案:
select之后指定你想要查询的列。
例如,只查看员工的名字、部门编号和工资。
select ename,deptno,sal from EMP;
结果:
ename | deptno | sal |
---|---|---|
SMITH | 20 | 800 |
ALLEN | 30 | 1600 |
WARD | 30 | 1250 |
JONES | 20 | 2975 |
MARTIN | 30 | 1250 |
BLAKE | 30 | 2850 |
CLARK | 10 | 2450 |
SCOTT | 20 | 3000 |
KING | 10 | 5000 |
TURNER | 30 | 1500 |
ADAMS | 20 | 1100 |
JAMES | 30 | 950 |
FORD | 20 | 3000 |
MILLER | 10 | 1300 |
1.5创建列的别名
问题:你可能想要修改检索结果的列名,使其更具可读性且更易于理解。考虑下面这个查询,它返回的是每个员工的工资。
select ename,sal from emp
ename是什么吗?sal 指的是什么?显然这不方便阅读查询结果。
检索结果应该让人容易理解,所以我们可以在查询的时候自定义查询结果显示的列名(当然这不会改变数据库中表的列名)。
解决方案:
使用 AS 关键字创建别名,以 original_name AS new_name 的形式来修改检索结果的列名。
对于一些数据库而言, AS 不是必需的,但所有的数据库都支持这个关键字。
【注意】自定义的显示列名(别名),不允许有空格
SQL语句:
select
ename as EmployeeName,
sal as salary
from EMP
where deptno=30;
结果:
EmployeeName | salary |
---|---|
ALLEN | 1600 |
WARD | 125 |
MARTIN | 1250 |
BLAKE | 2850 |
TURNER | 1500 |
JAMES | 950 |
1.6 在where子句中引用别名列
问题:根据1.5中,已经为检索结果创建了有意义的列名
现在想要利用where子句来进行数据的过滤
但是你按照下面的SQL语句,则无法成功
select
sal as salary ,
comm as commission
from EMP
where salary<5000
为什么呢?
【注意】
where子句会比select子句先执行
from子句会比where子句先执行
(from>where>select)
所以你在上面的查询语句的时候,在执行where子句的时候,根本就还没有slaray。
解决方案:
法1.你在where子句中使用原始列名
select
sal as salary ,
comm as commission
from EMP
where sal<5000
法2.把查询包装为一个内嵌视图
select *
from
(
select
sal as salary
comm as commission
from EMP
)
where salary<5000;
1.7 串联多列的值
问题:想要查询多列的值显示在一列上
比如说:
select ename,job
from EMP
where deptno=10
结果:
ename | job |
---|---|
CLARK | MANAGER |
KING | PRESIDENT |
MILLER | CLERK |
上面如愿查询到结果,但是想要显示为一列,如下:
msg |
---|
CLARK work as a MANAGER |
KING work as a PRESIDENT |
MILLER work as a CLERK |
怎么办呢?
解决方案:
select ename+' work as a ' +job as msg
from EMP
where deptno=10
结果:如上所希望。
1.8 在select语句里使用条件逻辑
问题:你想在 SELECT 语句中针对查询结果值执行 IF-ELSE 操作。
例如,你想生成类似这样的结果:
如果员工的工资少于 2000 美元,就返回 UNDERPAID ;
如果超过 4000 美元就返回OVERPAID ;
若介于两者之间则返回 OK 。
查询结果如下所示:
ENAME | SAL | Status |
---|---|---|
SMITH | 800 | UNDERPAID |
ALLEN | 1600 | UNDERPAID |
WARD | 1250 | UNDERPAID |
JONES | 2975 | OK |
MARTIN | 1250 | UNDERPAID |
BLAKE | 2850 | OK |
CLARK | 2450 | OK |
SCOTT | 3000 | OK |
KING | 5000 | OVERPAID |
TURNER | 1500 | UNDERPAID |
ADAMS | 1100 | UNDERPAID |
JAMES | 950 | UNDERPAID |
FORD | 3000 | OK |
MILLER | 1300 | UNDERPAI |
解决方案:
使用case语句
select ename ,sal ,
case
when sal>=4000 then 'OverPaid'
when sal<=2000 then 'UnderPaid'
else 'Ok'
end as Status
from EMP
结果如上所愿!
【说明】
case语句格式如下:
case
when 限制条件语句1 then '返回值1'
when 限制条件语句2 then '返回值2'
...
else '返回值'
end as 自定义列名
【注意】
1.else子句是可选的,若没有它,对于不满足测试条件的行, case 表达式会返回 Null 。
2.case语句就是相当于一个列,所以自己给他定义了一个列名(在end后使用as关键字),同样因此用逗号和其他列名隔开。
3.注意返回值是使用单引号,SQL中字符串使用单引号引起
1.9 限定返回行数
问题:想要限定返回结果的行数,而且不在意排序。
例如:返回查询结果的前5行。
解决方案:使用 TOP 关键字限定返回行数。
select top 5 *
from EMP
结果是返回EMP表的前5行
1.10 随机返回若干行记录
问题:希望从表中获取特定数量的随机记录。
解决方案:利用order by newid()与top子句配合,实现在记录集中获取N条随机记录
select top 5 *
from EMP
order by newid()
结果是随机的在EMP表中选取5行。
【说明】
在MS SQL中函数newid()
:
newid()函数产生一个全球唯一的标识,该标识是由网卡号、CPU时钟组成。从而保证该函数调用的返回值是唯一的。
该函数的返回值类型为uniqueidentifier类型,该类型必须与newid函数配合使用。
newid函数的用途:
正是由于uniqueidentifier的唯一性,我们通常用uniqueidentifier类型作为表的主键类型,通过newid函数为该类型的字段新增或者更新值。
【举例】
create table test
(
id uniqueidentifier primary key,
name varchar(20)
)
插入新的数据:
insert into test values ( newid() , '小明' )
1.11 查找 Null 值
问题:你想查找特定列的值为 Null 的所有行。
注意:NULL是指无值(no value),它与字段包含 0、空字符串或仅仅包含空格不同。
解决方案:判断一个值是否为 Null ,必须使用 IS Null
。
select * from EMP
where comm is NULL
结果就是EMP表中comm列值是NULL的所有数据。
【说明】毫无疑问,查找特定列的值是非NULL的方式就是使用is not null
1.12 把 Null 值转换为实际值
问题:有一些行包含 Null 值,但是你想在查询的返回结果里将其替换为非 Null 值。
注意:只是把你查询的结果中的NULL换成其他的值,并不是修改数据库的表。
解决方案1:使用使用 coalesce()
函数将 Null 值替代为实际值。
例如:如果EMP表中的comm列的值是NULL,则返回0,若非NULL则返回comm值
select coalesce(comm,0)
from EMP
【说明】
coalesce 动词,合并的意思,读作[,koə'lɛs]
COALESCE(expression_1, expression_2, ...,expression_n)依次参考各参数表达式,遇到非null值即停止并返回该值。如果所有的表达式都是空值,最终将返回一个空值
解决方案2:使用case语句,但是没有coalesce()函数简洁
顺便说一句主流数据库都自带coalesce()函数。
select
case
when comm is not null then comm
else 0
end as comm
from EMP
1.13 查找匹配项
问题:你想返回匹配某个特定字符串或模式的行。
例如:你想从编号为 10 和 20 的两个部门中找到名字中含有字母 I 或职位以 ER 结尾的人。
解决方案:使用通配符%
配合like
操作符
select ename, job
from emp
where deptno in (10,20)
and (ename like '%I%' or job like '%ER')
【说明】
最常使用的通配符是百分号( % ),所有DBMS皆支持。在搜索串中,
%
表示任何字符出现任意次数通配符 % 看起来像是可以匹配任何东西,但有个例外,这就是 NULL 。子句 WHERE name LIKE '%' 不会匹配产品名称为 NULL 的行。
MS SQL还有通配符
[]
,此处不详述了。
【注意】通配符不利于SQL优化
SQL 的通配符很有用。但这种功能是有代价的,即通配符搜
索一般比前面讨论的其他搜索要耗费更长的处理时间。
用通配符时要记住的技巧。
- 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
- 在确实需要使用通配符时,也尽量不要把它们用在搜索模式的开始处。把通配符置于开始处,搜索起来是最慢的