65

リンクされている 2 つのテーブルがあるとします (一方には他方への外部キーがあります)。

CREATE TABLE Document (
  Id INT PRIMARY KEY,
  Name VARCHAR 255
)

CREATE TABLE DocumentStats (
  Id INT PRIMARY KEY,
  DocumentId INT, -- this is a foreign key to table Document
  NbViews INT
)

これが最も賢明な方法ではないことはわかっていますが、これは私が思いつく最良の例です。

ここで、ビュー数が 500 を超えるすべてのドキュメントを取得したいと考えています。私の頭に浮かぶ2つの解決策は次のとおりです。

SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

また:

SELECT *
FROM Document
INNER JOIN DocumentStats ON Document.Id = DocumentStats.Id
WHERE DocumentStats.NbViews > 500

両方のクエリは同等ですか、それとも他の方法よりもはるかに優れた方法がありますか? もしそうなら、なぜですか?

編集:回答で要求されているように、この質問は SQL Server を対象としていましたが、他のデータベース エンジン (MySQL など) とは異なるかどうかを知りたいと思います。

4

10 に答える 10

49

理論的には、いいえ、これ以上速くなることはありません。クエリ オプティマイザーは、同一の実行プランを生成できる必要があります。ただし、一部のデータベース エンジンは、そのうちの 1 つに対してより優れた実行計画を作成できます (このような単純なクエリでは発生しない可能性がありますが、十分に複雑なクエリでは発生しません)。両方をテストして確認する必要があります (データベース エンジンで)。

于 2009-07-15T07:34:39.370 に答える
13

ターゲット データベースに限定せずにこれに正しく答える方法はありません。

MS-SQL の場合、両方のクエリで同じ実行プランが生成されますが、次の点に注意してください。

SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

WHERE 句の結合条件を忘れやすく、厄介なクロス結合になってしまうため、非常に危険です。

于 2009-07-15T07:38:04.263 に答える
4

少なくとも MySQL では、両方とも同じクエリに最適化されます。

于 2009-07-15T07:34:33.897 に答える
2

特に SQL Server について話している場合は、間違いなく INNER JOIN 構文を使用する必要があります。(個人的な意見ですが!) 読みやすく、意図がより明確であることは別として、SQL Server 2005 の時点では、外部結合に相当する構文はありません。*= および =* 構文は、2005 ではデフォルトでサポートされていません。これをサポートするには、互換モードを有効にする必要があります。最終的には、おそらく次のリリースですぐに削除されます (または削除されない可能性もあります!)。

これの意味は:

  • クエリを内部結合から外部結合に変更する必要がある場合は、クエリを書き直す (argh) か、互換モードを有効にする (yuk) 必要があります。
  • 互換モードがないと、さまざまなタイプの結合 (内部と外部) の実装方法に一貫性を持たせることができず、メンテナンスの悪夢が生じます (そして、1 つのクエリで 2 つが組み合わされると、直感的でない動作が発生します)。

一般に信じられていることとは反対に、この 2 つは同等ではないことにも注意してください。いくつかのことははるかに厄介であり、いくつかは単に不可能です. Kalen Delaney のInside SQL Server 2000 では、いくつかの例が取り上げられています。とにかくその結合構文は非推奨であるため、新しいエディションがそうするかどうかはわかりません。

于 2009-07-16T04:08:08.633 に答える
2

INNER JOIN 構文を使用することは「標準」ですが、実質的には同等です。これを使用する主な理由は、OUTER JOIN 構文と一貫性があるため、明確さとモビリティの目的のためです。

于 2009-07-15T07:41:40.340 に答える
2

Sqlite を使用する場合: Sqlite はクエリを実行する前にまず結合構文を where 構文に変換するため、where 構文の方がわずかに高速です。

于 2009-07-15T07:43:18.417 に答える
1

それも大差ないと思います。これら 2 つのクエリの説明計画が同一であるかどうかを確認できるようにします。MySQL で Explain Plan を確認するには、ステートメントの前に「explain」キーワードを配置する必要があります。たとえば、次のようになります。

EXPLAIN
SELECT *
FROM Document, DocumentStats
WHERE DocumentStats.Id = Document.Id
  AND DocumentStats.NbViews > 500

MSSQLにも同等のものが存在すると確信しています。

ところで、これは 1 対 1 の関係のように見えるので、nbviews 属性を Document テーブルに直接含めるだけで、結合を保存できます。

于 2009-07-15T08:04:03.290 に答える
1

MSSQL では、両方のクエリが同じ実行プランにコンパイルされるため、違いはありません。読みやすさの方が重要です。JOINの方が読みやすいと思うので、それを使用します。

于 2009-07-15T07:36:15.500 に答える