2017-05-11 36 views
0

3つのテーブルのデータを結合しようとしていますが、マイナーな問題があります。3つのSELECTステートメントを含むSQLステートメント

私はテーブルAからのすべてのレコードを取得したいのは、我々は3つのテーブル

表A

ID | ID2 | ID3 | Name | Age 
1 2x 4y John 23 
2 7j   Mike 27 
3 1S1 6HH Steve 67 
4 45 O8 Carol 56 

表B

| ID2 | ID3 | Price 
    2x 4y  23 
    7j 8uj  27 
    x4 Q6  56 

表C

|ID | Weight| 
    1 145 
    1 210 
    1 240 
    2 234 
    2 110 
    3 260 
    3 210 
    4 82 

を持っているとしましょうすべての人のwei ghs 200以上であるが、表Bに入れることはできません。表Aと表CはIDで結合されています。表AとBは、ID2またはID3のいずれかで結合されています。 ID2とID3の両方が必ずしも入力される必要はありませんが、少なくとも1つは入力されます。いずれかが存在しても、両方とも存在していても、どちらも一意になります。したがって、期待される結果は

3 | 1S1 | 6HH | Steve| 67 

です。人は複数の重みを持つことができますが、少なくとも1つのレコードが200以上であれば、それらは引っ張られます。私はこれを行うと、私が持っているもの

は、これまで

Select * 
From tableA x 
Where 
    x.id in (Select distinct y.id 
      From tableA y, tableC z 
      Where y.id = z.id 
       And z.weight >= '200' 
       And y.id not in (Select distinct h.id 
           From tableA h, tableB k 
           Where (h.id2 = k.id2 or h.id3 = k.id3))) 

TABLEBのチェックを無視するようだと私はジョン、マイクとスティーブを取得します。何か案は?申し訳ありませんが巻き込まれて、これは私が動作する必要があります。私は途中でこれをオラクルでやっています。

+1

[キックする悪い習慣:古いスタイルを使用してJOINを]テストデータである(http://sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08/古いスタイルのジョイン.aspx) - 古いスタイルのカンマで区切られたテーブル*スタイルのリストが、ANSIの*適切な* ANSI 'JOIN'構文に置き換えられました - ** 92 ** SQL標準(** 25 years ** ago)とその使用は避けてください –

答えて

3

existsnot existsのようになります。二つの別々のサブクエリにorは、多くの場合、パフォーマンス向上させることができます

select a.* 
from tableA a 
where exists (select 1 from tableC c where c.id = a.id and c.weight >= 200) and 
     not exists (select 1 from tableB b where b.id2 = a.id2 or b.id3 = a.id3); 

分割:だから、直接の翻訳がある

select a.* 
from tableA a 
where exists (select 1 from tableC c where c.id = a.id and c.weight >= 200) and 
     not exists (select 1 from tableB b where b.id2 = a.id2) and 
     not exists (select 1 from tableB b where b.id3 = a.id3); 
+0

テーブルCにexists句を使用するのはなぜですか? cに加わり、体重のwhere句を利用する方が良いのではないでしょうか?また、私は> 200であるべきだと思います – hisnameismyname2

+0

ありがとうございます。これはうまくいった。期待される結果が得られた。 – DanH

0
Select a.id, a.id2, a.id3 
From table_a a 
Left join table_c c on a.id = c.id 
Where c.weight >=200 
     And not exists 
     (Select 1 
     From table_b b 
     Where a.id = b.id2 
       Or a.id = b.id3 
     ); 
0
私は答えに破った

が、私はテーブルの上にINNER JOINを使用し、テーブルbのNOT EXISTS

--This first section is creating the test data 
with Table_A (id, id2, id3, Name, age) as 
    (select 1, '2x', '4y', 'John', 23 from dual union all 
    select 2, '7j', null,  'Mike', 27 from dual union all 
    select 3, '1S1', '6HH', 'Steve', 67 from dual union all 
    select 4, '45', 'O8', 'Carol', 56 from dual), 
Table_B(id2, id3, price) as 
    (select '2x', '4y',  23 from dual union all 
    select '7j', '8uj',  27 from dual union all 
    select 'x4', 'Q6',  56 from dual), 
Table_C(id, weight) as 
    (select 1, 145 from dual union all 
    select 1, 210 from dual union all 
    select 1, 240 from dual union all 
    select 2, 234 from dual union all 
    select 2, 110 from dual union all 
    select 3, 260 from dual union all 
    select 3, 210 from dual union all 
    select 4, 82 from dual) 
--Actual query starts here 
select distinct a.* 
from table_a a 
    --join to table c, include the weight filter 
    inner join table_c c on (a.id = c.id and c.weight >= 200)  
where not exists -- The rest is the NOT EXISTS to exclude the values in table b 
    (select 1 from table_b b 
    where a.id2 = b.id2 
     or a.id3 = b.id3); 
1

これは私が思いついたものです。 BELOW

SELECT DISTINCT 
    A.ID, 
    A.ID2, 
    A.ID3, 
    A.Name, 
    A.Age 
FROM 
        A 
    LEFT OUTER JOIN C ON C.ID = A.ID 
    LEFT OUTER JOIN B ON 
     B.ID2 = A.ID2 
    OR B.ID3 = A.ID3  
WHERE 
     C.Weight >= 200 
    AND B.Price IS NULL 

CREATE TABLE A 
(
    ID INT, 
    ID2 VARCHAR(3), 
    ID3 VARCHAR(3), 
    Name VARCHAR(10), 
    Age INT 
); 

INSERT INTO A VALUES (1, '2x', '4y', 'John', 23); 
INSERT INTO A VALUES (2, '7j', NULL , 'Mike', 27); 
INSERT INTO A VALUES (3, '1S1', '6HH', 'Steve', 67); 
INSERT INTO A VALUES (4, '45', 'O8', 'Carol', 56); 

CREATE TABLE B 
(
    ID2 VARCHAR(3), 
    ID3 VARCHAR(3), 
    Price INT 
); 

INSERT INTO B VALUES ('2x', '4y', 23); 
INSERT INTO B VALUES ('7j', '8uj', 27); 
INSERT INTO B VALUES ('x4', 'Q6', 56); 

CREATE TABLE C 
(
    ID INT, 
    Weight INT 
); 

INSERT INTO C VALUES (1, 145); 
INSERT INTO C VALUES (1, 210); 
INSERT INTO C VALUES (1, 240); 
INSERT INTO C VALUES (2, 234); 
INSERT INTO C VALUES (2, 110); 
INSERT INTO C VALUES (3, 260); 
INSERT INTO C VALUES (3, 210); 
INSERT INTO C VALUES (4, 82); 
+0

これは、ソリューションが存在することを避け、存在しない句をすべて一緒に使用するため、私の答えよりも効率的です。私から+ 1、しかし200以上になる必要があります – hisnameismyname2

+0

> 200に更新しました。そして、私は存在を避けようとしていた/存在しません。例のような小さなテーブルは大したことではないかもしれませんが、非常に大きなデータセットを持つそれらのキーにインデックスを持たせれば、ジョインはもっとうまく機能するはずです。彼らが避けることができれば外の結合の巨大なファンではないが、このシナリオで私は彼らが呼び出されると思います。 –

関連する問題