sql连接查询中,where关键字的位置讲解

由于笔者天生笨拙,且思维不严谨,也实在不擅长写sql语句,高手请勿见笑,就请直接跳过本文吧。

背景就不多介绍了,先建表,插入测试数据吧。字段那些都有注释


代码如下:

--医生表
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' )

表建好之后,测试数据也OK。下面开始说需求啦。

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

这简直太简单了,可能连刚学会helloWorld和一点点数据库基础的朋友都会严重真心BS。不过代码还是写出来。


代码如下:

--简单的分组查询即可搞定
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。抬头仰望天空40度,想想能够用where关键字过滤,然后一次性查询出来吗?试试吧。


代码如下:

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

这样去解释,不知道大家是否能够理解,反正大致意思就是这样的。笔者的表达能力和水平确实有限,难免有偏差,望读者谅解!

(0)

相关推荐

  • sql连接查询中,where关键字的位置讲解

    由于笔者天生笨拙,且思维不严谨,也实在不擅长写sql语句,高手请勿见笑,就请直接跳过本文吧. 背景就不多介绍了,先建表,插入测试数据吧.字段那些都有注释 复制代码 代码如下: --医生表CREATE TABLE doctor    (      id INT IDENTITY(1, 1) , --ID 自增长      docNumber NVARCHAR(50) NOT NULL , --医生编码      NAME NVARCHAR(50) NOT NULL   --医生姓名    )go

  • 浅谈sql连接查询的区别 inner,left,right,full

    --table1 表 ID NAME QQ PHONE 1 秦云 10102800 13500000 2 在路上 10378 13600000 3 LEO 10000 13900000 4 秦云 0241458 54564512 --table2 表 ID NAME sjsj gly 1 秦云 2004-01-01 00:00:00.000 李大伟 2 秦云 2005-01-01 00:00:00.000 马化腾 3 在路上 2005-01-01 00:00:00.000 马化腾 4 秦云 20

  • mysql连接查询中and与where的区别浅析

    1. 建表 CREATE TABLE `student` ( `id` int(11) NOT NULL, `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL, `age` int(11) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8mb4 CO

  • sql连接查询语句中on、where筛选的区别总结

    前言 相信对于每位程序员来说,sql查询这个东西, 要说它简单, 可以很简单, 通常情况下只需使用增删查改配合编程语言的逻辑表达能力,就能实现所有功能. 但是增删查改并不能代表sql语句的所有, 完整的sql功能会另人望而生畏. 就拿比普通增删查改稍微复杂一个层次的连接查询来说, 盲目使用, 也会出现意料之外的危险结果,导致程序出现莫名其妙的BUG. 在连接查询语法中,另人迷惑首当其冲的就要属on筛选和where筛选的区别了, 在我们编写查询的时候, 筛选条件的放置不管是在on后面还是where

  • SQL连接查询介绍

    连接可以在Select 语句的FROM子句或Where子句中建立,似是而非在FROM子句中指出连接时有助于将连接操作与Where子句中的搜索条件区分开来.所以,在Transact-SQL中推荐使用这种方法. SQL-92标准所定义的FROM子句的连接语法格式为: FROM join_table join_type join_table [ON (join_condition)] 其中join_table指出参与连接操作的表名,连接可以对同一个表操作,也可以对多表操作,对同一个表操作的连接又称做自

  • SQL中的连接查询详解

    Join 连接 (SQL Join) SQL Join (连接) 是利用不同数据表之间字段的关连性来结合多数据表之检索. SQL Join是结合多个数据表而组成一抽象的暂时性数据表以供数据查询,在原各数据表中之纪录及结构皆不会因此连接查询而改变. 这是一个客户数据表「customers」: C_Id Name City Address Phone 1 张一 台北市 XX路100号 02-12345678 2 王二 新竹县 YY路200号 03-12345678 3 李三 高雄县 ZZ路300号

  • SQL Sever查询语句大全集锦

    一. 简单查询 简单的Transact-SQL查询只包括选择列表.FROM子句和WHERE子句.它们分别说明所查询列.查询的 表或视图.以及搜索条件等. 例如,下面的语句查询testtable表中姓名为"张三"的nickname字段和email字段. 代码:SELECT `nickname`,`email`FROM `testtable`WHERE `name`='张三' (一) 选择列表 选择列表(select_list)指出所查询列,它可以是一组列名列表.星号.表达式.变量(包括局

  • SQL Server查询语句大全集锦

    一. 简单查询 简单的Transact-SQL查询只包括选择列表.FROM子句和WHERE子句.它们分别说明所查询列.查询的 表或视图.以及搜索条件等. 例如,下面的语句查询testtable表中姓名为"张三"的nickname字段和email字段. 代码:SELECT `nickname`,`email`FROM `testtable`WHERE `name`='张三' (一) 选择列表 选择列表(select_list)指出所查询列,它可以是一组列名列表.星号.表达式.变量(包括局

  • mysql连接查询详解

    目录 1.连接查询 2.连接类型 内连接 定义: 语法1: 语法2: 3个表连接 显示指定列 左连接 定义: 语法: 右连接 定义: 语法: 自关联 定义 子查询 定义 主查询 主查询和子查询的关系 子查询充当条件 子查询充当数据源 子查询中特定关键字使用 1.连接查询 作用:当查询结果的列来源于多张表时,需要将多张表连接成一个大的数据集,再选择合适的列返回 2.连接类型 内连接 定义: 内连接查询:查询结果为两个表匹配到的数据 语法1: select * from 表1 inner join

  • MySQL笔记之连接查询详解

    连接查询是将两个或两个以上的表按某个条件连接起来,从中选取需要的数据 当不同的表中存在表示相同意义的字段时,可以通过该字段来连接这几张表 参考表:employee 参考表:department 可以看到,上面两张表都有同一个字段d_id 当两张表含有相同意义的字段(可以不同名)时就可以进行连接查询 内连接查询 复制代码 代码如下: mysql> SELECT num, name, employee.d_id, sex, d_name, function    -> FROM employee,

随机推荐