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

最近一直在忙,也没有太多时间停留下来写博客。晚上遇到一个觉得很有趣的sql题,可能对初学者和我这种菜鸟会有帮助,所以决定分享给大家。

由于笔者天生笨拙,且思维不严谨,也实在不擅长写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 

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

本文出自http://blog.csdn.net/dinglang_2009,转载请注明出处。

时间: 2024-08-30 12:19:39

sql连接查询中,where关键字的位置的相关文章

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

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

StreamRead和sqlparamter,sql连接查询

  StreamRead和sqlparamter,sql连接查询以及分页整理 -> Xml操作 InnerText 会对标签<>转义 InnerXml 不会对标签转义 委托 多播委托. --写入txt StreamWrite 写入文本 reader.FieldCount得到字段的个数 StreamWrite对象的WriteLine()方法就可以把读取的内容写入到txt中 StreamRead 读取文本 string temp; while((temp = reader.ReadLine(

sql连接查询,修改列值

问题描述 sql连接查询,修改列值 两表连接查询,需要将其中一列的值加到另一列上(两列在分别两张表中): update (select * from g3_buybudgetg3_budget_plan where g3_buybudget.budgetno in (select budgetno from g3_budget_plan where buyplanno = 1031))set remainingmoney = remainingmoney + thismoney 提示我不能修改该

sql子查询中列别名在主查询中无效

问题描述 sql子查询中列别名在主查询中无效 CREATE PROCEDURE dbo.query_test( @i_begin_time varchar(128) IN, /* 开始时间 / @i_end_time varchar(128) IN, / 结束时间 / @i_bussiness_tpe varchar(512) IN, / 类型 ) as declare @v_sql varchar(16384)/* 定义 需要执行的sql / declare @Rtime varchar(12

sql连接语句中的Integrated Security=SSPI/ture/false

erver=localhost;database=Northwind; integrated security=SSPI  Microsoft安全支持提供器接口(SSPI)是定义得较全面的公用API,用来获得验证.信息完整性.信息隐私等集成安全服务,以及用于所有分布式应用程序协议的安全方面的服务.应用程序协议设计者能够利用该接口获得不同的安全性服务而不必修改协议本身. 上面这句话的意思就是这个连接采用了这个接口,如果没有定义就会出错! Integrated Security 身份验证方式 当为f

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

--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

SQL连接查询1 内联接查询

在数据库开发方面,通过单表所表现的实现,有时候需要组合查询来找到我们需要的记录集,这时候我们就会用到连接查询. 连接查询主要包括以下几个方面: 内连接 内连接一般是我们最常使用的,也叫自然连接,是用比较运算符比较要联接列的值的联接.它是通过(INNER JOIN或者JOIN)关键字把多表进行连接.我们通过建立两个表来说明问题: StudentID StudentName StudentAge----------- -----------------------------------------

SQL 连接查询语法及使用

  一.交叉连接(cross join) 交叉连接(cross join):有两种,显式的和隐式的,不带on子句,返回的是两表的乘积,也叫笛卡尔积. 例如:下面的语句1和语句2的结果是相同的. 语句1:隐式的交叉连接,没有cross join. select o.id, o.order_number, c.id, c.name from orders o , customers c where o.id=1; 语句2:显式的交叉连接,使用cross join. select o.id,o.ord

T-SQL命令在SQL Server查询中的运用

server 首先需要说明的是这篇文章的内容并不是如何调节SQL Server查询性能的(有关这方面的内容能写一本书),而是如何在SQL Server查询性能的调节中利用SET STATISTICS IO和SET STATISTICS TIME这二条被经常忽略的Transact-SQL命令的. 从表面上看,查询性能的调节是一件十分简单的事.从本质上讲,我们希望查询的运行速度能够尽可能地快,无论是将查询运行的时间从10分钟缩减为1分钟,还是将运行的时间从2秒钟缩短为1秒种,我们最终的目标都是减少运