sql連線查詢中,where關鍵字的位置

2021-06-08 17:30:13 字數 3382 閱讀 2000

最近一直在忙,也沒有太多時間停留下來寫部落格。晚上遇到乙個覺得很有趣的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

這樣去解釋,不知道大家是否能夠理解,反正大致意思就是這樣的。筆者的表達能力和水平確實有限,難免有偏差,望讀者諒解!

sql連線查詢中,where關鍵字的位置

最近一直在忙,也沒有太多時間停留下來寫部落格。晚上遇到乙個覺得很有趣的sql題,可能對初學者和我這種菜鳥會有幫助,所以決定分享給大家。由於筆者天生笨拙,且思維不嚴謹,也實在不擅長寫sql語句,高手請勿見笑,就請直接跳過本文吧。背景就不多介紹了,先建表,插入測試資料吧。字段那些都有注釋 醫生表 cre...

sql連線查詢中on篩選與where篩選的區別

sql查詢這個東西,要說它簡單,可以很簡單,通常情況下只需使用增刪查改配合程式語言的邏輯表達能力,就能實現所有功能。但是增刪查改並不能代表sql語句的所有,完整的sql功能會另人望而生畏。就拿比普通增刪查改稍微複雜乙個層次的連線查詢來說,盲目使用,也會出現意料之外的危險結果,導致程式出現莫名其妙的b...

sql連線查詢中on篩選與where篩選的區別

sql查詢這個東西,要說它簡單,可以很簡單,通常情況下只需使用增刪查改配合程式語言的邏輯表達能力,就能實現所有功能。但是增刪查改並不能代表sql語句的所有,完整的sql功能會另人望而生畏。就拿比普通增刪查改稍微複雜乙個層次的連線查詢來說,盲目使用,也會出現意料之外的危險結果,導致程式出現莫名其妙的b...