2011-09-14 66 views
3

我有三個表(這裏簡化)NULL和ISNULL(STR,NULL):是不是在WHERE子句

recipients: recipientId, isGroup 
users: userId, first name, last name 
groups: groupid, groupname 

我想中檢索第一個名稱/姓名,如果收款人是一個用戶,如果收件人是一個組,則爲組名。接收者可能不是(即一個被刪除/不再存在的組),所以在這種情況下我不想返回任何東西。

所以這是我做過什麼:

select u.first_name, u.last_name, g.groupname, r.isGroup 
from recipients r 
left join users u on u.userid = r.recipientId 
left join groups g on g.groupid = r.recipientId 
where r.isGroup IS NULL or g.groupname IS NOT NULL 

上面的查詢沒有返回預期的結果。我得到這個回:

adam, smith, null, null 
yolanda, smith, null, null 
null, null, members, 1 
null, null, null, 1 

最後一行是意想不到的,因爲很明顯,沒有組名(g.groupname是NULL)和r.IsGroup = 1

當我這樣做:

select u.first_name, u.last_name, g.groupname, r.isGroup 
from recipients r 
left join users u on u.userid = r.recipientId 
left join groups g on g.groupid = r.recipientId 
where r.isGroup IS NULL 

我得到預期的結果:

adam, smith, null, null 
yolanda, smith, null, null 

當我這樣做:

select u.first_name, u.last_name, g.groupname, r.isGroup 
from recipients r 
left join users u on u.userid = r.recipientId 
left join groups g on g.groupid = r.recipientId 
where g.groupname IS NOT NULL 

我得到預期的結果:

null, null, members, 1 

只有當我與OR結合兩個where子句,我會得到更多的排。

現在,當我改變我的查詢到(其他城市從IS NULL到ISNULL):

select u.first_name, u.last_name, g.groupname, r.isGroup 
from recipients r 
left join users u on u.userid = r.recipientId 
left join groups g on g.groupid = r.recipientId 
where r.isGroup IS NULL or ISNULL(g.groupname, null) IS NOT NULL 

我得到預期的結果:

adam, smith, null, null 
yolanda, smith, null, null 
null, null, members, 1 

事實上,我甚至不有要改變where子句,下面的查詢也同樣適用,並給出了上面顯示的預期結果:

select u.first_name, u.last_name, ISNULL(g.groupname,null), r.isGroup 
from recipients r 
left join users u on u.userid = r.recipientId 
left join groups g on g.groupid = r.recipientId 
where r.isGroup IS NULL or g.groupname IS NOT NULL 

S O,問題是,爲什麼? 爲什麼在我的SELECT語句中放置ISNULL會改變WHERE子句的工作方式?爲什麼它有所作爲? 爲什麼我的第一個查詢不起作用?爲什麼只有當我添加OR時它纔會發揮作用 - 爲什麼它沒有被破壞呢?

在此先感謝。

我使用MS SQL Server 2008的

編輯:固定錯字,澄清問題

+0

您能否確保g.groupname包含NULL值而不是像「NULL」這樣的字符串。有時候可能會讓你困惑。 –

+0

是的。我確實確定。除此之外,如果沒有,ISNULL(g.groupname,null)IS NOT NULL不會有任何區別。 – Swati

回答

4

我們發現這是Sql Server 2008中沒有安裝Service Pack的問題。嘗試安裝SP1或SP2。在我們的例子中,該服務包解決了這個問題。

2

ISNULL是retuns指定的輸入值,如果列爲空,否則柱值的函數。

ISNULL(tbl.x, 'y') --returns 'y' if tbl.x is null otherwise the value of tbl.x 
+0

你打我:) –

+0

然後這是等價的:ISNULL(g.groupname,null)是不是NULL和g.groupName IS不爲NULL,對吧?由於g.groupname爲空時,ISNULL將解析爲null。但是,我的查詢表明它不相同。 – Swati

0

從SELECT子句:

u.groupname

從WHERE子句:

g.groupname

讓這兩場比賽,讓我們知道你是否看到任何不同。

+0

哦,對不起,錯字。假設它也是SELECT子句中的g.groupname。 – Swati

2

我相信你要做的就是獲取所有用戶和組,如果它是用戶first_name和last_name將是某事,並且groupname將是NULL,但是如果它是一個組,則first_name和last_name將爲NULL, groupname會是一些東西。相反,您的WHERE子句將過濾結果,而不是定義數據連接的條件。我認爲這將讓你在尋找什麼(假設r.isGroup == 1意味着它是一個組):

要使用更多或更少的原始查詢,但消除了一個不存在的組或用戶記錄:

select u.first_name, u.last_name, g.groupname, r.isGroup 
from recipients r 
left join users u 
    on u.userid = r.recipientId and r.isGroup != 1 
left join groups g 
    on g.groupid = r.recipientId and r.isGroup == 1 
where u.userid IS NOT NULL or g.groupid IS NOT NULL 

不過,我認爲有內工會的加入將有更好的表現:

select u.first_name, u.last_name, NULL, r.isGroup 
from recipients r 
inner join users u on u.userid = r.recipientId 
where r.isGroup != 1 
union 
select NULL, NULL, g.groupname, r.isGroup 
from recipients r 
inner join groups g on g.groupid = r.recipientId 
where r.isGroup == 1 
+0

即使當r.IsGroup = 1時,它也可能不是一個組(或者任何關於這個問題的東西)。我想省略在任何一個表中都找不到的結果,這些結果僅在r.IsGroup = 1時發生,並且它不在組表中(發生是因爲可以刪除組)。我無法這樣做。 – Swati

+0

我更新了我的案例。 – six8

+0

謝謝。但我已經知道如何得到我想要的結果,我只是想知道爲什麼我的第一個查詢不起作用,但第二個查詢不起作用 - 唯一的區別是使用ISNULL。此外,你的第一個查詢給我同樣的確切問題 - 我的原始查詢給我。它不起作用並返回應該被過濾掉的額外行。 – Swati

0

這似乎得到你想要的結果,但如果有從NULLS任何陷阱瑞士cheesing您的數據可能無法正常工作:

select u.first_name, u.last_name, g.groupname, r.isGroup 
from #recipients r 
left join #users u on u.userid = r.recipientId 
left join #groups g on g.groupid = r.recipientId 
WHERE g.groupname IS NOT NULL 
    OR ISNULL(r.IsGroup,0) > CASE WHEN g.groupid IS NOT NULL AND g.groupname IS NULL THEN -1 ELSE 0 END