2016-06-29 3 views
0

Это правильно?nvl, Где, IN статьи

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

a, b - столбцы в t1 для идентификатора от t2.

Я хочу, чтобы все строки, которые имеют идентификатор для «Apple» либо в T1.a или T1.b

если имеет нулевое значение, идентификатор будет в б.

если b равно null, идентификатор будет в a.

+0

Ваш код выглядит так, как будто он делает то, что вы хотите. Я предпочитаю 'coalesce()', стандартную функцию ANSI. –

+0

Кажется, я не получаю результаты, которые я ожидаю с помощью этой логики. – Skn

+0

Уверен ли, что хотя бы один из обоих и b является нулевым? – trincot

ответ

2

Я хочу, чтобы все строки, которые имеют идентификатор для «Apple» либо в T1.a или T1.b

Нет, это не правильно.

Ваш запрос получит строки, где t1.a находится в t2id или где t1.a является null и t1.b в t2id.

Вы хотите:

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. , , Хотя я предпочитаю 'exist' для исходной логики, это эквивалентно. Вы неверно процитировали OP, оставив «если a имеет значение null, id будет в b, если b равно null, id будет в a». Это то же самое, что и ваша логика. Проблема, как представляется, будет описана в комментарии (без сомнения, написана после того, как вы ответили). '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

Если значения и б в одной записи являются -9999 и идентификатор яблока, ваш запрос не возвращает записи, потому что не равно нулю, и так -9999 сравнивается с яблоком ID, а не значение б

Я предлагаю это, при условии, что у вас есть только одна запись в 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

Да, это было предположение, которое я сделал. Я уже упомянул об этом в своем ответе и предоставил альтернативу, когда могли существовать несколько записей Apple. – 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'); 
Смежные вопросы