3

ばかげた質問かもしれませんが、次の 2 つのテーブルを考えてみてください。

T1                       
Store    Year
01  2009
02  2009
03  2009
01  2010
02  2010
03  2010

T2
Store
02

この INNER JOIN が私が望む結果を与えるのはなぜですか (ON 句で [年] をフィルタリングする):

select t1.*
from t1
inner join t2
on t1.store = t2.store
and t1.[year] = '2009'

Store    Year
02  2009

また、LEFT OUTER JOIN に 2010 年のレコードが含まれているのはなぜですか?

select t1.*
from t1
left outer join t2
on t1.store = t2.store
and t1.year = '2009'
where t2.store is null

01  2009
03  2009
01  2010
02  2010
03  2010

そして、「WHERE」句に [year] フィルターを記述する必要があります。

select t1.*
from t1
left outer join t2
on t1.store = t2.store
where t2.store is null
and t1.year = '2009'

01  2009
03  2009

私が言ったように、おそらくばかげた質問ですが、それは私を悩ませています!

4

2 に答える 2

3

LEFT JOIN の定義に従うと、

  • 左側のテーブルの各行に対して、右側のテーブルから一致する行が存在する場合はそれを返します
  • 右側に行が存在しない場合でも、右側のテーブルのすべての列が NULL に設定された左側のテーブルから行が返されます。

ここで、exist は ON 条件と同等であり、true と評価され、すべて意味があることを理解してください。

t1.year が 2010 の行では、on 式は false と評価されます (t1.year = 2010 のすべての行で x AND 2010=2009 は false) が、左結合であるため、左側のテーブルの行が返されます。 (定義によると)。

したがって、この種の条件は、join 条件ではなく、where 条件としてのみ記述できます。

(一般的に、テーブルである必要はなく、select 式である必要があります)

編集: Erwin が興味深いことに指摘したように、 where 条件を JOIN に変えることができます

select t1.*
from t1
left outer join t2
on t1.store = t2.store
or t1.year = '2009'
where t2.store is null

なぜなら:

t1.store t1.year t2.store t1.store=t2.store t1.year=2009  join(OR)
01       2009    02       false             true          true
02       2009    02       true              true          true
03       2009    02       false             true          true
01       2010    02       false             false         false
02       2010    02       true              false         true
03       2010    02       false             false         false

したがって、上記のテーブルの結合列がfalseである行のみが t2.* フィールドに null を返します。

私が言いたかったのは、この種の条件は純粋な結合に変換できないということです。これは、左結合の方法が機能するためです (結合条件が false の場合でもレコードを返します)。結合し、逆も同様です)。

提案されたクエリについて - 私のアドバイスは、それを使用しないことです。

OR を使用したクエリは、一般的な規則として AND 条件を使用したクエリよりもパフォーマンスが低下します (OR は結果セットを拡張し、AND は制限します)。これは、join 条件と where 条件の両方に適用されます。

あなたのクエリは、where 条件で t1.year = '2009' を含むクエリよりもパフォーマンスが低下します。これは、後でインデックスを使用できるため (存在する場合)、同じように結合すると、基本的にあるテーブルのレコードを別のテーブルのレコードと人為的に結合して、where 条件が必要なレコードのみをフィルター処理するようにします。最初に 2009 年を持つ t1 からレコードのみを取得する方が効果的です (年のインデックスがあり、WHERE 条件で発生する選択性が十分に高いと仮定します)。

パフォーマンスに関するこれらの提案は両方とも、クエリ プランを調べることで検証できますし、検証する必要があります。

最後に、クエリは少しあいまいです。t1.year = '2009' の場合、結合がデカルト積になることはすぐにはわかりません (これは後で除外されます)。LEFT JOINそのため、シンプルでwhere t1.year = 2009 AND t2.store is nullパフォーマンスが向上し、AND が読みやすいという仮定があれば、このクエリは使用しません。

于 2010-04-13T10:26:47.770 に答える
0

2番目のクエリは、結合で一致したものを除いて、最初のテーブルからすべての結果を返します(その結果は最初のクエリで確認できます)。これは、「where t2.store is null」句を指定し、選択した列に「t2.Store」を追加します。その場合に表示される結果は次のとおりです。

01 2009 null
02 2009 02
03 2009 null
01 2010 null
02 2010 null
03 2010 null

ご覧のとおり、t2.storeがnullである行だけにフィルターをかけると、2番目の行(join句に一致した唯一の行)を減算するだけです。

于 2010-04-13T10:11:43.187 に答える