zoukankan      html  css  js  c++  java
  • 《SQL CookBook 》笔记-第一章-检索记录

    第一章
    shanzm



    1.1检索所有行和列

    问题:你有一张表,并且想查看表中的所有数据。

    解决方案1:

    select * from EMP
    

    解决方案2:

     select empno,ename,job,sal,mgr,hiredate comm,deptno from EMP
    

    说明:

    建议使用方案2,因为别人看你的代码的时候不一定知道你查询的表里面的列,所以还是写出查询的具体列更方便阅读。其次从优化的角度来说,尽量避免“ select * ” 的存在,使用具体的列代替*,避免返回多余的列。

    【技巧】

    1. 查看SQL语句执行时间:
    set statistics time on
    
    select * from EMP  
    -- 注释:这里写你要测试执行时间的SQL语句
    
    set statistics time off
    

    运行结束之后,从消息栏,可以查看

    SQL Server 执行时间:
    CPU 时间 = 0 毫秒,占用时间 = 0 毫秒。

    1. 查看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()

    1. newid()函数产生一个全球唯一的标识,该标识是由网卡号、CPU时钟组成。从而保证该函数调用的返回值是唯一的。

    2. 该函数的返回值类型为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')
    

    【说明】

    1. 最常使用的通配符是百分号( % ),所有DBMS皆支持。在搜索串中, % 表示任何字符出现任意次数

    2. 通配符 % 看起来像是可以匹配任何东西,但有个例外,这就是 NULL 。子句 WHERE name LIKE '%' 不会匹配产品名称为 NULL 的行。

    3. MS SQL还有通配符[],此处不详述了。

    【注意】通配符不利于SQL优化

    SQL 的通配符很有用。但这种功能是有代价的,即通配符搜
    索一般比前面讨论的其他搜索要耗费更长的处理时间。

    用通配符时要记住的技巧。

    • 不要过度使用通配符。如果其他操作符能达到相同的目的,应该使用其他操作符。
    • 在确实需要使用通配符时,也尽量不要把它们用在搜索模式的开始处。把通配符置于开始处,搜索起来是最慢的


  • 相关阅读:
    WCF JSON DATETIME JSON.NET (Newtonsoft.Json.dll)
    fastboot 重启到recovery
    EXCEL datatable 根据列名自动写入到相应属性、字段或列中
    支付宝通讯时异常 基础连接已经关闭
    c#.net 调用BouncyCastle生成PEM格式的私钥和公钥
    WCF 遇到 由于线程退出或应用程序请求,已放弃 I/O 操作 ListenerContextInputStream
    runliuv, 安卓查看WIFI密码
    安卓 NEXUS6 修改分辨率,density
    ubuntu 安装 VISUAL STUDIO CODE
    C# .NET MVC 接收 JSON ,POST,WCF 无缝隙切换
  • 原文地址:https://www.cnblogs.com/shanzhiming/p/10357783.html
Copyright © 2011-2022 走看看