2016-06-29 68 views
0

這是正確的嗎?nvl,其中,IN子句

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

a,b是來自t2的Id中的t1列。

我希望所有對「蘋果」無論是在t1.a或t1.b

如果爲空,ID將在B ID行。

如果b爲空,則id將在a中。

+0

你的代碼看起來像它做你想做的。我更喜歡'coalesce()',ANSI標準函數。 –

+0

我似乎沒有得到我期待的結果與這個邏輯。 – Skn

+0

確定a和b中至少有一個是否爲空? – trincot

回答

2

我希望所有對「蘋果」無論是在t1.a或t1.b

不,這是不正確的ID行。

您的查詢後可得到t1.at2id行或者t1.anullt1.bt2id

你想:

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

或:

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

或者(如果需要強制執行的非匹配值的NULL):

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

這應該怎麼寫?它只能用OR來書寫嗎? – Skn

+0

@Skn更新爲帶有'OR' – MT0

+0

@ MT0的替代品。 。 。雖然我更喜歡「存在」原始邏輯,但它是等價的。通過忽略「如果a爲null,id將在b中;如果b爲null,id將在a中」,您錯誤地引用了OP。這與你的邏輯一樣。這個問題似乎是在評論中描述的(無疑是在你回答後寫的)。 'a'也可以包含-9999。 –

1

這是正確的,但效率低下。 我會寫

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

錯了。聯盟放棄重複。 – wolfrevokcats

0

如果在一個記錄一個b的值-9999和蘋果的ID,你的查詢將不會返回的記錄,因爲一個不爲空,所以-9999與蘋果ID進行比較,而不是的b

值我的建議是,假設你有一個紀錄只有T2表示「蘋果」

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

如果你能在T2名爲「蘋果」有多個記錄那麼我建議這樣的:

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

如果'name'不是唯一的列,那麼你將得到'ORA-01427:單行子查詢返回多行'。 – MT0

+0

是的,這是我做的一個假設。我現在在回答中已經提到了它,並提供了多種蘋果記錄可以存在的替代方案。 – trincot

0

你的問題在註釋中描述 - 在問題中的邏輯不正確,因爲值可能是-9999。你可以做你想要的:

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');