2017-12-15 21 views
0

私はOracle 11gを実行していますが、これはより一般的なSQLの質問です。SQL JOINが必要な結果を返さない

だから私は、次のテーブル/データを持っている -

CREATE TABLE TEST_GROUP (
    ID VARCHAR2(20), 
    CONSTRAINT test_group_pk PRIMARY KEY (ID) 
); 
INSERT INTO TEST_GROUP VALUES ('AAA'); 

CREATE TABLE GROUP_PREFERENCE (
    GROUP_ID VARCHAR2(20), 
    ID VARCHAR2(20), 
    TYPE VARCHAR2(20), 
    CONSTRAINT GROUP_PREF_PK PRIMARY KEY (GROUP_ID, ID, TYPE) 
); 
INSERT INTO GROUP_PREFERENCE VALUES ('AAA', 'AAA-P1', 'CONFIGURABLE'); 
INSERT INTO GROUP_PREFERENCE VALUES ('AAA', 'AAA-P2', 'ENABLED'); 

CREATE TABLE PREFERENCE_ENTRY (
    PREFERENCE_ID VARCHAR2(20), 
    PREFERENCE_VALUE VARCHAR2(20), 
    CONSTRAINT PREF_PK PRIMARY KEY (PREFERENCE_ID, PREFERENCE_VALUE) 
); 
INSERT INTO PREFERENCE_ENTRY VALUES ('AAA-P1', 'TRUE'); 
INSERT INTO PREFERENCE_ENTRY VALUES ('AAA-P2', 'TRUE'); 

マイSQL -

SELECT g.ID 
FROM TEST_GROUP g 
JOIN GROUP_PREFERENCE gp ON g.ID = gp.GROUP_ID 
JOIN PREFERENCE_ENTRY pe ON gp.ID = pe.PREFERENCE_ID 
WHERE (
     (gp.TYPE = 'CONFIGURABLE' AND pe.PREFERENCE_VALUE = 'TRUE') 
     AND 
     (gp.TYPE = 'ENABLED' AND pe.PREFERENCE_VALUE = 'TRUE') 
    ) 

私はSQLがTEST_GROUP 'AAA' を返すようにしたいが、私はテストしていので、それはのように見えますどちらもPREFERENCE_ENTRY値ではありません。私がどちらか1つをテストすると、行は返されますしかし両方のPREFERENCE_ENTRYエントリが 'TRUE'であることをテストする必要があります。

あなたSQL達人から任意の助けが最も理解されるであろう...

私は、これは非常に簡単であると確信しているが、私はそれに苦しんでいます。

ありがとうございます。

+3

gp.TYPE = 'CONFIGURABLE'とgp.TYPE = 'ENABLED'は真ではありませんすべて –

答えて

1

あなたはgroup byhavingを使用することができます。 Oracleはまた、あなたがinを使って何をしたいのかについての素敵な速記を持っています。ここ

SELECT g.ID 
FROM TEST_GROUP g JOIN 
    GROUP_PREFERENCE gp 
    ON g.ID = gp.GROUP_ID JOIN 
    PREFERENCE_ENTRY pe 
    ON gp.ID = pe.PREFERENCE_ID 
WHERE (gp.TYPE, pe.PREFERENCE_VALUE) IN (('CONFIGURABLE', 'TRUE'), ('ENABLED', 'TRUE')) 
GROUP BY g.ID 
HAVING COUNT(DISTINCT gp.TYPE) = 2; 
+0

HAVINGが必要な理由について少し説明してください。それはそれなしで動作するようですか? – Hallam

+2

両方のタイプを含むグループだけを表示する必要があるためです。 –

2

条件が使用どこでORないと

(...) 
WHERE (
     (gp.TYPE = 'CONFIGURABLE' AND pe.PREFERENCE_VALUE = 'TRUE') 
     OR 
     (gp.TYPE = 'ENABLED' AND pe.PREFERENCE_VALUE = 'TRUE') 
    ) 

編集:

SELECT g.ID 
FROM TEST_GROUP g 
JOIN GROUP_PREFERENCE gp1 ON g.ID = gp1.GROUP_ID and gp1.TYPE='CONFIGURABLE' 
JOIN GROUP_PREFERENCE gp2 ON g.ID = gp2.GROUP_ID and gp2.TYPE='ENABLED' 
JOIN PREFERENCE_ENTRY pe1 ON gp1.ID = pe1.PREFERENCE_ID 
JOIN PREFERENCE_ENTRY pe2 ON gp2.ID = pe2.PREFERENCE_ID 
WHERE pe1.PREFERENCE_VALUE = 'TRUE' and pe2.PREFERENCE_VALUE = 'TRUE' 
+0

しかし、もし*両方が真であれば、行が返されます。 – Hallam

+1

'gp.TYPE'はどのように2つの値に等しいでしょうか? – syrion

+0

はい、私はそれが問題だと知っています。しかし、両方の 'preferences'がTRUEの場合にのみ 'AAA'が返されます。 – Hallam

2

はストレートなアプローチのように見えるかもしれません別のオプションです。

WHERE句が1行を参照し、1行のタイプが「CONFIGURABLE」にすることはできませんし、「有効」ので、あなたは、あなたがテーブルを結合して、「CONFIGURABLE」と「有効」をチェックするためにWHERE句を使用できないことに気づきました同時に。

あなたが代わりに行うだろうが、メインテーブルから選択され、(INは2の簡単です)EXISTSまたはINWHERE句で他のテーブルを検索してください。ゴードンによって示されるように

select id 
from test_group 
where id in 
(
    select gp.group_id 
    from group_preference gp 
    join preference_entry pe on gp.id = pe.preference_id 
    where gp.type = 'CONFIGURABLE' and pe.preference_value = 'TRUE' 
) 
and id in 
(
    select gp.group_id 
    from group_preference gp 
    join preference_entry pe on gp.id = pe.preference_id 
    where gp.type = 'ENABLED' and pe.preference_value = 'TRUE' 
); 

は、単純にいえ簡単です group_preferencepreference_entryの上に集約し、好ましい方法は、(あなたが彼のクエリからテーブル TEST_GROUPを削除することができます - それが必要ではないです)。しかし時々、 EXISTSまたは INで検索が必要な状況があるので、私はちょうどその方法について言及したいと思いました:-)

関連する問題