3

私は3つのテーブルを持っています(ここで簡略化されています):

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

明らかにグループ名がなく(たとえば、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

2つのwhere句をORと組み合わせた場合にのみ、追加の行を取得できます。

ここで、クエリを(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

だから、問題は、なぜですか?SELECTステートメントにISNULLを入れると、WHERE句の動作が変わるのはなぜですか?なぜそれがまったく違いを生むのですか?最初のクエリが機能しないのはなぜですか?ORを追加した場合にのみ機能しないのはなぜですか?ORを追加しないと壊れないのはなぜですか?

前もって感謝します。

MS SQLServer2008を使用しています。

編集:タイプミスを修正し、質問を明確にしました

4

5 に答える 5

4

これは、サービスパックがインストールされていないSQLServer2008の問題であることがわかりました。SP1またはSP2をインストールしてみてください。この場合、サービスパックで問題が解決しました。

于 2011-09-22T18:15:15.280 に答える
2

ISNULLは、列がnullの場合は指定された入力値を再調整し、それ以外の場合は列値を再調整する関数です。

ISNULL(tbl.x, 'y') --returns 'y' if tbl.x is null otherwise the value of tbl.x
于 2011-09-14T19:29:35.740 に答える
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
于 2011-09-14T19:40:18.257 に答える
0

SELECT 句から:

u.グループ名

WHERE 句から:

g.グループ名

これらの 2 つを一致させて、何か違うことがわかったらお知らせください。

于 2011-09-14T19:33:18.180 に答える
0

これはあなたが望む結果を得るように見えますが、NULLS swiss-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
于 2011-09-14T20:13:10.677 に答える