I have to compare two tables with identical structure (int not null,int not null, varchar2). In both tables field3 is a nullable.
I have the next SQL:
Select
t1.field1, t1.field2, t1.field3)
From
table1 t1
Where (field1,field2,field3)
not in
(select field1,
field2,field3
from table2 t2)
When the field3 is NULL in any of them (t1 or t2) the query does not return any row. For instance I want to return a row from this data but it returns nothing at all.
Table 1
field1 field2 field3
1 2 <NULL>
Table 2
field1 field2 field3
1 2 'some text data'
There is workaround to fix such thing by using the NVL function: NVL(field3, 'dummytextorwhatever') but I dont want to include such horrible thing into my code. Any idea to solve this problem with nullable fields?
Thank you!
This is known behavior with NOT IN when there are nulls in either the main table or the sub-query's result sets. As #DrCopyPaste puts it so well
"when writing WHERE value NOT IN (x, y, z) this will be internally interpreted as WHERE value != x AND value != y AND value != z, and comparing against NULL (either for equality or unequality) always yields FALSE"
The simple answer is to use NOT EXISTS:
Select
t1.field1, t1.field2, t1.field3)
From
table1 t1
Where not exists
(select null from table2 t2
where t2.field1 = t1.field1
and t2.field2 = t1.field2
and t2.field3 = t1.field3 )
An anti-join will produce the same result
Select
t1.field1, t1.field2, t1.field3)
From
table1 t1
left join table2 t2
on t2.field1 = t1.field1
and t2.field2 = t1.field2
and t2.field3 = t1.field3
where t2.field1 is null
"why do you select a null at the beginning?"
Because with NOT EXISTS it doesn't matter what the sub-query returns. All that matters is that it returns a non-empty result set. It could have been 1 or field1 but it really doesn't matter, so why not null?
Try to use NVL or Coalesce operators, like this
Select
t1.field1, t1.field2, t1.field3
From
table1 t1
Where (nvl(field1,0),nvl(field2,0),nvl(field3,0))
not in
(select nvl(field1,0),nvl(field2,0),nvl(field3,0)
from table2 t2)
but if in tables data there is some data equals 0 select will be return that row, because nvl(field1,0)=nvl(field2,0) when field1=0 and field2=null, so you can use any value(you should be confident
) wich no exists in your tables data for example -99(nvl(field,-99))
or you can use exists/not exists
Try not exists
Select
t1.field1,
t1.field2,
t1.field3
From
table1 t1
where not exists
(select 1
from table2 t2
where
t1.field1=t2.field1
and t1.field2=t2.field2
and t1.field3=t2.field3
)
Sample test
with table1(field1,field2,field3) as
(select 1,2,null from dual),
table2(field1,field2,field3) as
(select 1,2,'something' from dual)
Select
t1.field1,
t1.field2,
t1.field3
From
table1 t1
where not exists
(select 1
from table2 t2
where
t1.field1=t2.field1
and t1.field2=t2.field2
and t1.field3=t2.field3
)
Output
FIELD1 FIELD2 FIELD3
1 2
Based on your query, you are trying to find all the times in table1 that do not exist in table2. Instead of NOT IN, consider using a MINUS...
Select t1.field1, t1.field2, t1.field3
From table1 t1
Minus
select t2.field1, t2.field2, t2.field3
from table2 t2;
This is my statement
select * from table1
where col1 not in (select col2 from table2);
I want to try(but failed)
select t1.* from table1 t1
inner join table2 on t1.col1<> t2.col2
Is there another way to do this?
select t1.* from table1 t1
left join table2 t2 on t1.col1 = t2.col2
where t2.col2 is null
This is standard implementation of missing record search.
To get the records that exists in table1 but does't exists in table2 you need a left join, not an inner join.
Try this:
select t1.*
from table1 t1
left join table2 t2 on t1.col1 = t2.col2
where t2.id is null -- any non-nullable column will do, best to use pk for performance.
You have not defined t2 object and use left join.
SELECT t1.* FROM table1 t1
LEFT JOIN table2 t2 ON t2.col2 = t1.col1 WHERE t2.id IS NULL
If You try to find out the data of t1.c1 (t1=table1, c1=column1) that is exist or not exist in t2.c2 then use flowing script
select t1.c1 from t1 left join t2 on t1.c1=t2.c2
other wise if you want to find only t1.c1 data that is not in t2.c2 then below script is help full
select t1.c1 from t1 where t1.c1 not in (select t2.c2 from t2)
My requirement is like :
select (*ALL columns of table1, [count of rows of TABLE2 where TABLE1.id = Table2.id]
from TABLE1, TABLE2
where TABLE1.status = 'A'
Am now to SQL, please pardon if the question is too simple
select t1.col1, t1.col2, t1.col3, count(t2.id)
from table1 t1
left join TABLE2 t2 on t1.id = t2.id
where t1.status = 'A'
group by t1.col1, t1.col2, t1.col3
Using correlated subquery:
SELECT t1.*
,(SELECT COUNT(*) FROM TABLE2 t2 WHERE t1.id = t2.id) AS Counter
FROM TABLE1 t1
WHERE t1.status = 'A';
I feel like there should be a simpler way to write this, since both SELECT statements are pulling from the same table:
SELECT column1
FROM table1
WHERE column2 = 'VIRTUAL'
AND column3 IN
(SELECT column3
FROM table1
WHERE column1 = 'ELEC-035A');
Here is the same query but i replaced the subquery by an INNER JOIN clause:
SELECT T1.column1
FROM table1 T1
INNER JOIN table1 T2 ON T2.column3 = T1.column3
AND T2.column1 = 'ELEC-035A'
WHERE T1.column2 = 'VIRTUAL'
GROUP BY T1.column1
Hope this will help.
I have three tables Table1, Table2 and Table3 and the following query which deletes rows in Table1
delete from Table1
where EXISTS
(select (1) from Table2
where Table1.col1=Table2.col1
AND Table1.col2=Table2.col2
AND Table1.col3=(select **Table3.col3 from Table3** inner join Table2 on Table3.col1=Table2.col1)
Is this query correct? If not, how to use a third table inside the where condition?
Edit : Also, please explain how to rewrite the query if we want to delete the rows from table2 which itself is joined with table3?
Here's one way to do it:
delete from table1
where (col1, col2, col3) in (
select t1.col1, t1.col2, t1.col3
from table1 t1
join table2 t2 on t1.col1 = t2.col1 and t1.col2 = t2.col2
join table3 t3 on t1.col3 = t3.col3 and t2.col1 = t3.col1
);
SQL Fiddle Demo
Or using EXISTS might be faster:
delete table1
where exists (
select *
from table2
join table3 on table2.col1 = table3.col1
where table1.col3 = table3.col3 and
table1.col1 = table2.col1 and
table1.col2 = table2.col2);