0

仮定の状況: 私は特注看板製作会社で働いており、一部のクライアントは、現在使用しているよりも多くの看板デザインを提出しています。使用されたことのない標識を知りたい。

関連する 3 つのテーブル:

表 A - 会社の標識

sign_pk(ユニーク) | company_pk | sign_description
1 --------------------1 ---------------- 小
2 ---------- -----------------------1 ---------------- 大
3 -------------------- 2 ---------------- ミディアム
4 --------------------2 ---------- ------ ジャンボ
5 --------------------3 ---------------- バナー

表 B - 会社の所在地

company_pk | company_location (一意)
1 ------|------ 987
1 ------|------ 876
2 ------|------ 456
2 ------|------ 123

表 C - 場所の標識 (少し大げさですが、各行には 2 つの標識を含めることができ、会社の場所から場所の標識への 1 対多の関係です)

会社の場所 | フロントサイン | back_sign
987 ------------ 1 ------------ 2
987 ------------ 2 -------- ---- 1
876 ------------ 2 ------------ 1
456 ------------ 3 ---- -------- 4
123 ------------ 4 ------------ 3

したがって、a.company_pk = b.company_pk および b.company_location = c.company_location です。私が試して見つけたいのは、sign_pk 5 がどの場所にもないことを照会して取得する方法です。すべてのテーブルに何百万もの行があるため、すべての front_sign および back_sign 値に対して各 sign_pk をクエリすることは、少し非現実的です。テーブル a は sign_pk と company_pk でインデックス付けされ、テーブル b は両方のフィールドでインデックス付けされ、テーブル c は会社の場所のみでインデックス付けされます。私が書き込もうとしている方法は、「各標識は会社に属しているため、その標識に関連付けられている会社に属する場所のいずれかで、前面または背面の標識ではない標識を見つけてください」という行に沿っています。

私の当初の計画は次のとおりでした。
Select a.sign_pk
from a, b, c
where a.company_pk = b.company_pk
and b.company_location = c.company_location
and a.sign_pk *= c.front_sign
group by a.sign_pk having count(c.front_sign) = 0

前の記号を実行してから後ろの記号を繰り返すだけですが、 c は外部結合の内部メンバーであり、内部結合でもあるため、実行されません。

この全体はかなり複雑ですが、誰かがそれを理解できるなら、私はあなたの親友になります.

4

3 に答える 3

1

このようなものはどうですか:

  SELECT DISTINCT sign_pk
    FROM table_a
   WHERE sign_pk NOT IN
    (   
      SELECT DISTINCT front_sign sign
        FROM table_c
       UNION
      SELECT DISTINCT rear_sign sign
       FROM  table_c
    )
于 2010-04-17T03:14:21.353 に答える
0

内部結合用の一時テーブルを作成してから、それを外部結合したくなるでしょう。ただし、実際にはデータセットのサイズに依存します。はい、スキーマの設計に欠陥がありますが、常に修正できるとは限りません。

于 2011-11-16T15:01:14.967 に答える
0

ANSI 外部結合は、ここでの友達です。*= は危険なセマンティクスを持っているため、避ける必要があります

select distinct a.sign_pk, a.company_pk
from a join b on a.company_pk = b.company_pk 
left outer join c on b.company_location = c.company_location 
                  and (a.sign_pk = c.front_sign or a.sign_pk = c.back_sign) 
where c.company_location is null

where句は結合によって返された行に対するフィルターであるため、「結合を行いますが、 cに結合しなかった行のみを提供してください」と表示されていることに注意してください。

ほとんどの場合、外部結合は NOT EXISTS および NOT IN より高速です

于 2010-04-24T11:46:26.677 に答える