2016-06-29 11 views
0

Ist das korrekt?nvl, Wo, IN-Klauseln

select * from t1 
where nvl(t1.a,t1.b) in (select id from t2 where name = 'Apple') 

a, b sind die Spalten in t1 für die Id aus t2.

Ich möchte alle Zeilen, die ID für 'Apple entweder in t1.a oder T1.B

haben, wenn eine Null ist, id in b sein.

Wenn b null ist, wird id in a sein.

+0

Ihr Code sieht aus wie es tut, was Sie wollen. Ich bevorzuge 'coalesce()', die ANSI-Standardfunktion. –

+0

Ich scheine nicht die Ergebnisse zu erhalten, die ich mit dieser Logik erwarte. – Skn

+0

Ist es sicher, dass mindestens einer von beiden und null ist? – trincot

Antwort

2

Ich möchte alle Zeilen, die ID für 'Apple entweder in t1.a oder T1.B

haben Nein, es ist nicht richtig.

Ihre Anfrage wird die Zeilen, wo t1.a ist ein id in t2 oder wo t1.a ist null und t1.b ist ein id in t2.

Sie wollen:

select * 
from t1 
where EXISTS (select 1 
       from t2 
       where name = 'Apple' 
       and (t1.a = t2.id OR t1.b = t2.id)) 

oder:

SELECT * 
FROM t1 
WHERE a IN (SELECT id FROM t2 WHERE name = 'Apple') 
OR  b IN (SELECT id FROM t2 WHERE name = 'Apple') 

oder (wenn Sie die NULL in der nicht passenden Wert erzwingen):

select * 
from t1 
where EXISTS (select 1 
       from t2 
       where name = 'Apple' 
       and ( (t1.a = t2.id AND t1.b IS NULL) 
         OR (t1.b = t2.id AND t1.a IS NULL))) 
+0

wie soll das geschrieben werden? Kann es nur mit einem OR geschrieben werden? – Skn

+0

@Skn Aktualisiert mit einer Alternative mit einem 'OR' – MT0

+0

@ MT0. . . Obwohl ich es vorziehe, existiert 'exist' zu der ursprünglichen Logik, es ist äquivalent. Sie haben das OP falsch zitiert, indem Sie "weggelassen haben, wenn a null ist, wird id in b sein; wenn b null ist, wird id in a sein." Das ist das Gleiche wie deine Logik. Das Problem scheint in einem Kommentar beschrieben zu sein (ohne Zweifel geschrieben, nachdem Sie geantwortet haben). 'a' kann auch -9999 enthalten. –

1

es korrekt ist, aber ineffizient. Ich würde schreiben

select * from t1 
where t1.a in (select id from t2 where name = 'Apple') 
union 
select * from t1 
where t1.b in (select id from t2 where name = 'Apple') 
+1

Falsch. Union verwirft Duplikate. – wolfrevokcats

0

Wenn die Werte für ein und b in einem Datensatz sind -9999 und die ID von Apple, Ihre Abfrage wird die Aufzeichnung nicht zurück, weil ein nicht null ist, und so -9999 wird mit der Apfel-ID verglichen, nicht dem Wert von b

ich schlage vor, dies unter der Annahme, dass Sie nur ein Datensatz in t2, die das repräsentiert „Apple“:

select * 
from t1 
where (select id from t2 where name = 'Apple') in (a, b) 

Wenn Sie mehrere Datensätze in t2 mit dem Namen "Apple" dann würde ich vorschlagen, dies haben könnte:

select  distinct t1.* 
from  t1 
inner join t2 
     on t2.name = 'Apple' 
     and t2.id in (t1.a, t1.b) 
+0

Wenn 'name' keine eindeutige Spalte ist, erhalten Sie' ORA-01427: einreihige Unterabfrage gibt mehr als eine Zeile zurück. – MT0

+0

Ja, es war eine Annahme, die ich gemacht habe. Ich habe es jetzt in meiner Antwort erwähnt und eine Alternative für den Fall bereitgestellt, dass mehrere Apple-Datensätze existieren könnten. – trincot

0

Ihr Problem in dem Kommentar beschrieben wird - die Logik in der Frage ist nicht korrekt, weil ein Wert -9999 sein könnte. Sie können tun, was Sie wollen als:

select * 
from t1 
where (case when t1.a is null or t1.a = -9999 then t1.b else t1.a end) in 
     (select id from t2 where name = 'Apple'); 
Verwandte Themen