42

データベースクエリを書き始めたとき、私はまだ JOIN キーワードを知りませんでした。当然、すでに知っていることを拡張して、次のようなクエリを書きました。

SELECT a.someRow, b.someRow 
FROM tableA AS a, tableB AS b 
WHERE a.ID=b.ID AND b.ID= $someVar

これが INNER JOIN と同じであることがわかったので、コード内のこれらすべてのクエリを見つけて、それらを書き直す必要があるかどうかを自問します。それらに何か臭いがありますか、それとも大丈夫ですか?


私の回答の要約:このクエリには何も問題はありませんが、キーワードを使用すると、おそらくコードが読みやすく/保守しやすくなります。

私の結論: 古いクエリは変更しませんが、今後は書き方を修正し、キーワードを使用します。

4

11 に答える 11

38

のみを使用して結合をフィルタリングするWHEREことは、一部の一般的なシナリオでは非常に非効率的です。例えば:

SELECT * FROM people p, companies c 
    WHERE p.companyID = c.id AND p.firstName = 'Daniel'

ほとんどのデータベースは、このクエリを文字どおりに実行します。最初にとテーブルのデカルト積を取得し、一致するとフィールドを持つものでフィルタリングします。完全に制約のない積はメモリ内に存在するだけで、その瞬間だけ存在しますが、その計算には時間がかかります。peoplecompaniescompanyIDid

より良いアプローチはJOIN、関連する s で制約をグループ化することです。これは主観的に読みやすいだけでなく、はるかに効率的です。したがって:

SELECT * FROM people p JOIN companies c ON p.companyID = c.id
    WHERE p.firstName = 'Daniel'

ON少し長くなりますが、データベースは句を見て、それを使用して、すべてJOINから始めてから制限するのではなく、完全に制約されたものを直接計算できます。これは計算が高速で (特に大規模なデータ セットや多テーブル結合の場合)、必要なメモリが少なくて済みます。

「コンマJOIN」構文を使用するすべてのクエリを変更します。私の意見では、その存在の唯一の目的は簡潔さです。パフォーマンスへの影響を考えると、これはやむを得ない理由ではないと思います。

于 2008-09-24T19:43:40.067 に答える
10

より冗長なのINNER JOIN, LEFT OUTER JOIN, RIGHT OUTER JOIN, FULL OUTER JOINは、結合のための ANSI SQL/92 構文からのものです。私にとって、この冗長性により、結合の意図が開発者/DBA に対してより明確になります。

于 2008-09-24T18:41:26.067 に答える
6

SQL Server には常にチェックするクエリ プランがあり、テキスト出力は次のように作成できます。

SET SHOWPLAN_ALL ON
GO

DECLARE @TABLE_A TABLE
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Data VARCHAR(10) NOT NULL
)
INSERT INTO @TABLE_A
SELECT 'ABC' UNION 
SELECT 'DEF' UNION
SELECT 'GHI' UNION
SELECT 'JKL' 

DECLARE @TABLE_B TABLE
(
    ID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
    Data VARCHAR(10) NOT NULL
)
INSERT INTO @TABLE_B
SELECT 'ABC' UNION 
SELECT 'DEF' UNION
SELECT 'GHI' UNION
SELECT 'JKL' 

SELECT A.Data, B.Data
FROM
    @TABLE_A AS A, @TABLE_B AS B
WHERE
    A.ID = B.ID

SELECT A.Data, B.Data
FROM
    @TABLE_A AS A
    INNER JOIN @TABLE_B AS B ON A.ID = B.ID

テーブル変数の作成の計画は省略しますが、両方のクエリの計画は同じです。

 SELECT A.Data, B.Data  FROM   @TABLE_A AS A, @TABLE_B AS B  WHERE   A.ID = B.ID
  |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID]))
       |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A]))
       |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD)
 SELECT A.Data, B.Data  FROM   @TABLE_A AS A   INNER JOIN @TABLE_B AS B ON A.ID = B.ID
  |--Nested Loops(Inner Join, OUTER REFERENCES:([A].[ID]))
       |--Clustered Index Scan(OBJECT:(@TABLE_A AS [A]))
       |--Clustered Index Seek(OBJECT:(@TABLE_B AS [B]), SEEK:([B].[ID]=@TABLE_A.[ID] as [A].[ID]) ORDERED FORWARD)

つまり、短い答えです。メンテナンスのたびに長い時間をかけて読もうとしない限り、書き直す必要はありませんか?

于 2008-09-24T18:51:31.067 に答える
5

それは構文の選択です。結合条件を結合でグループ化することを好むため、INNER JOIN 構文を使用します

SELECT a.someRow, b.someRow
FROM tableA AS a
INNER JOIN tableB AS b
  ON a.ID = b.ID
WHERE b.ID = ?

(? はプレースホルダーです)

于 2008-09-24T18:41:18.937 に答える
4

一般に:

JOIN キーワードを使用して、主キーと外部キーをリンク (つまり「結合」) します。

WHERE 句を使用して、結果セットを関心のあるレコードのみに制限します。

于 2008-09-24T19:46:40.327 に答える
4

発生する可能性のある問題の 1 つは、同じクエリで古い「カンマ スタイル」結合と SQL-92 結合を混在させようとした場合です。たとえば、1 つの内部結合と別の外部結合が必要な場合です。

SELECT *
FROM table1 AS a, table2 AS b
 LEFT OUTER JOIN table3 AS c ON a.column1 = c.column1
WHERE a.column2 = b.column2;

問題は、最近の SQL 標準では、コンマ結合の前に JOIN が評価されると述べていることです。そのため、ON 句が評価されているときに相関名がまだ定義されていないため、ON 句で "a" を参照するとエラーが発生します。これは非常に紛らわしいエラーです。

解決策は、結合の 2 つのスタイルを混在させないことです。古いコードで引き続きコンマ スタイルを使用できますが、新しいクエリを作成する場合は、すべての結合を SQL-92 スタイルに変換してください。

SELECT *
FROM table1 AS a
 INNER JOIN table2 AS b ON a.column2 = b.column2
 LEFT OUTER JOIN table3 AS c ON a.column1 = c.column1;
于 2008-09-24T19:49:26.247 に答える
4

あなたの例の構文に問題はありません。「INNER JOIN」構文は一般に「ANSI」構文と呼ばれ、例に示されているスタイルの後に来ました。結合のタイプ/方向/構成要素を明確にするために存在しますが、一般的に、あなたが持っているものと機能的に違いはありません。

「ANSI」結合のサポートはデータベース プラットフォームごとですが、最近では多かれ少なかれ普遍的になっています。

補足として、「ANSI」構文で追加されたのは、「FULL OUTER JOIN」または「FULL JOIN」です。

お役に立てれば。

于 2008-09-24T18:40:27.630 に答える
3

暗黙の結合は避けます。クエリが非常に大きい場合、コードの解読が困難になります

明示的な結合と適切なフォーマットにより、コードはコメントを必要とせずに読みやすく、理解しやすくなります。

于 2008-09-24T18:40:51.560 に答える
2

また、この方法で内部結合を行っているのか、外部結合を行っているのかによっても異なります。たとえば、WHERE句(=*および*=)の外部結合のMS SQL Server構文は、OUTER JOIN構文とは異なる結果をもたらす可能性があり、サポートされなくなりました(http://msdn.microsoft.com/en-us SQL Server 2005の/library/ms178653(SQL.90).aspx )。

于 2008-09-24T18:59:30.393 に答える