24

ユーザーがドキュメントをダウンロードしたかどうかを示す列を含むクエリを作成しようとしています。次の列を持つ HasDownloaded というテーブルがあります: id、documentID、memberID。ユーザーが特定のドキュメントをダウンロードしたかどうかを調べるのは簡単です。しかし、結果が次のようになるクエリを生成する必要があります。

name              id
----------------------
abc               NULL
bbb               2
ccc               53
ddd               NULL
eee               13

ID はそれほど重要ではありません。私が興味を持っているのは、ドキュメントがダウンロードされているかどうか (NULL かどうか) です。

これが私のクエリです:

SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id
WHERE HasDownloaded.memberID = @memberID

問題は、HasDownloaded テーブルに指定されたユーザーのエントリが存在する場合にのみ、値が返されることです。これを単純にして、HasDownloaded にダウンロード済みのドキュメントのエントリのみを保持したいと考えいます。したがって、ユーザー 1 が abc、bbb、および ccc をダウンロードした場合でも、結果のテーブルに ddd と eee が表示され、ID が NULL になるだけです。しかし、WHERE 句は、エントリが存在する値のみを提供します。

私は SQL の専門家ではありません。ここで必要なものを提供してくれる演算子はありますか? 別のアプローチをとるべきですか?それともこれは不可能ですか?

4

3 に答える 3

43

WHERE 句の条件を結合条件に移動します。

SELECT Documents.name, HasDownloaded.id FROM Documents
LEFT JOIN HasDownloaded ON HasDownloaded.documentID = Documents.id 
  AND HasDownloaded.memberID = @memberID 

これは、そうでなければ WHERE 句で左結合されたテーブルを参照する場合に必要です。

于 2008-10-20T16:27:46.473 に答える
4
WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId

それを行う通常の方法になります。次のように短縮する人もいます。

WHERE COALESCE(HasDownloaded.memberId, @memberId) = @memberId

Matt B. が示すように、JOIN 条件で実行できますが、それは人々を混乱させる可能性がはるかに高いと思います。JOIN 句に移動する理由がわからない場合は、それを避けることを強くお勧めします。

于 2008-10-20T16:58:10.107 に答える
3

@Mark: JOIN 構文が機能する理由は理解していますが、警告をありがとう。あなたの提案はより直感的だと思います。どちらがより効率的かを知りたいと思っていました。そこで、簡単なテストを実行しました (これはかなり単純化されていて、14 行と 10 回の試行のみでした)。

JOIN 条件では:

AND HasDownloaded.memberID = @memberID
  • クライアント処理時間: 4.6
  • 合計実行時間: 35.5
  • サーバー応答の待ち時間: 30.9

WHERE 句で:

WHERE HasDownloaded.memberId IS NULL OR HasDownloaded.memberId = @memberId
  • クライアント処理時間: 7.7
  • 合計実行時間: 27.7
  • サーバー応答の待機時間: 22.0

WHERE 句のほうが少し効率的であるように見えます。面白い!改めまして、お二人のご協力に感謝いたします。

于 2008-10-20T17:46:11.743 に答える