sql连接查询中where关键字的位置优化

发布时间:2020-09-05编辑:脚本学堂
本文介绍下,在sql连接查询中,有关where关键字的放置位置的问题,如何放置性能才更好呢?有需要的朋友参考下吧。

本节内容:
sql查询中where关键字的位置。

下面用一段测试数据来说明where关键字放在什么位置,性能才好。

首先,建表,插入测试数据吧。注意其中的注释。

表:
 

复制代码 代码示例:

--医生表
CREATE TABLE doctor
    (
      id INT IDENTITY(1, 1) , --ID 自增长
      docNumber NVARCHAR(50) NOT NULL , --医生编码
      NAME NVARCHAR(50) NOT NULL   --医生姓名
    )
go
--插入测试数据
INSERT  INTO doctor
VALUES  ( '007', 'Tom' )
INSERT  INTO doctor
VALUES  ( '008', 'John' )
INSERT  INTO doctor
VALUES  ( '009', 'Jim' )

--号源表(挂号表)
CREATE TABLE Nosource
    (
      id INT IDENTITY(1, 1) ,
      docNumber NVARCHAR(50) NOT NULL , --和医生表中的医生编码对应
      workTime DATETIME NOT NULL
    )
go
--插入测试数据
INSERT  INTO Nosource
VALUES  ( '007', '20120819' )
INSERT  INTO Nosource
VALUES  ( '007', '20120820' )
INSERT  INTO Nosource
VALUES  ( '007', '20120821' )
INSERT  INTO Nosource
VALUES  ( '008', '20120821' )

1,查出每位医生的相关信息,以及该医生所拥有的号源数量。
 

复制代码 代码示例:
--简单的分组查询即可搞定
SELECT  COUNT(nos.id) AS PersonNumSounceCOUNT , --总数
        dct.ID AS docID ,
        dct.NAME ,
        dct.docNumber ,
        nos.workTime
FROM    doctor AS dct
        LEFT JOIN Nosource AS nos ON dct.docNumber = nos.docNumber
GROUP BY dct.ID ,
        dct.NAME ,
        dct.docNumber ,
        nos.workTime

需求改变:
按条件去匹配:要求号源表的workTime大于当前日期才算有效的,否则就不匹配。
如果workTime条件不匹配的医生,对应的PersonNumSounceCOUNT字段的值应为0 ;
例如:Jim医生没有匹配和符合条件的号源,其PersonNumSounceCOUNT字段值应为0。
代码:
 

复制代码 代码示例:
SELECT  COUNT(nos.id) AS PersonNumSounceCOUNT , --总数
        dct.ID ,
        dct.NAME ,
        dct.docNumber ,
        nos.workTime
FROM    doctor AS dct
        LEFT JOIN Nosource AS nos ON dct.docNumber = nos.docNumber
WHERE   datediff(day, GETDATE(), nos.workTime) > 0
GROUP BY dct.ID ,
        dct.NAME ,
        dct.docNumber ,
        nos.workTime

可是执行查询后,发现完全不符合要求啊。连Jim医生的基本信息和表记录也都被过滤掉了?

在连接查询的后面使用"where"关键字,会过滤连接查询的结果集中的数据。
由于右表(号源表)的条件不匹配,也会导致左表(医生表)的数据被过滤掉。
所以,会出现以上的现象(Jim医生的信息和记录都不见了)。要想一次性查出来可能吗?到底该如何去实现呢?

正确的写法:
 

复制代码 代码示例:
SELECT  COUNT(nos.id) AS PersonNumSounceCOUNT , --总数
        dct.ID ,
        dct.NAME ,
        dct.docNumber ,
        nos.workTime
FROM    doctor AS dct
        LEFT JOIN ( SELECT  *
                    FROM    Nosource
                    WHERE   DATEDIFF(day, GETDATE(), workTime) > 0
                  ) AS nos ON dct.docNumber = nos.docNumber
GROUP BY dct.ID ,
        dct.NAME ,
        dct.docNumber ,
        nos.workTime

再执行一下,果然OK,是满足要求的结果。

思路:只需要过滤右表,就将(使用子查询)过滤后的结果集作为连接查询的右表,然后再去连接,分组......
其实编写简洁而高性能的sql语句,是需要很强的逻辑思维能力(和数学分不开)和经验的。

更简单的写法:
 

复制代码 代码示例:
SELECT  sum(case when nos.workTime>getdate then 1 else 0 end) AS PersonNumSounceCOUNT , --总数
dct.ID AS docID ,
dct.NAME ,
dct.docNumber
FROM    doctor AS dct
LEFT JOIN Nosource AS nos ON dct.docNumber = nos.docNumber
GROUP BY dct.ID ,
dct.NAME ,
dct.docNumber

就介绍这些了,希望对大家掌握 sql server中where关键字的用法,有一定的帮助吧。