Reputation: 3364
This error seems to be popular and there are many related answers. However, the existing answers do not seem to apply to my situation.
I am simplifying my case using 2 tables: Test1 and Test3 (see illustration)
What I am trying to do is attempting to find the records in test3 table that does not match the value in field value1 (if the field check_condition1 = 1 if it is 0 then I do not care)
so basically the result should be similar to this query in this particular scenario:
select distinct t3.* from test3 t3, test1 t1
where t3.department=t1.department
and t3.value1 not in ('A','B');
However, if I use this statement:
select distinct t3.* from test3 t3, test1 t1
where t3.department=t1.department
and t3.value1 not in
(
case t1.CHECK_CONDITION1
when 0 then
(select '1' from dual where 1=2)
when 1 then
( select value1 from test1 where department=t3.DEPARTMENT)
end
)
I got this message:
ORA-01427: single-row subquery returns more than one row
01427. 00000 - "single-row subquery returns more than one row"
*Cause:
*Action:
I thought my subquery "select value1 from test1 where department=t3.DEPARTMENT" should return a set for t3.value1 to check against.
How should the statement be corrected? My goal is to use Test1 table as a control table, the fields Check_condition1, check_condition2 are the "switches" that could be turn on and off without having to change the main query. Please advise if my thought make sense.
Attached are the script to create the tables test1 and test3 for easier duplication of my issue.
CREATE TABLE "TEST1"
( "DEPARTMENT" NUMBER(3,0),
"VALUE1" VARCHAR2(26 BYTE),
"VALUE2" VARCHAR2(26 BYTE),
"CHECK_CONDITION1" NUMBER(3,0),
"CHECK_CONDITION2" NUMBER(3,0)
)
Insert into TEST1 (DEPARTMENT,VALUE1,VALUE2,CHECK_CONDITION1,CHECK_CONDITION2) values (1,'A','Z',1,0);
Insert into TEST1 (DEPARTMENT,VALUE1,VALUE2,CHECK_CONDITION1,CHECK_CONDITION2) values (1,'B','Y',1,0);
CREATE TABLE "TEST3"
( "DEPARTMENT" NUMBER(3,0),
"VALUE1" VARCHAR2(26 BYTE),
"VALUE2" VARCHAR2(26 BYTE),
"VALUE3" VARCHAR2(26 BYTE)
);
Insert into TEST3 (DEPARTMENT,VALUE1,VALUE2,VALUE3) values (1,'A','T','Whatever');
Insert into TEST3 (DEPARTMENT,VALUE1,VALUE2,VALUE3) values (1,'Z','Y','Whatever');
Insert into TEST3 (DEPARTMENT,VALUE1,VALUE2,VALUE3) values (1,'B','Y','Whatever');
Upvotes: 0
Views: 420
Reputation: 167877
From the CASE
expression documentation:
For both simple and searched
CASE
expressions, all of thereturn_expr
s must either have the same datatype (CHAR
,VARCHAR2
,NCHAR
, orNVARCHAR2
,NUMBER
,BINARY_FLOAT
, orBINARY_DOUBLE
) or must all have a numeric datatype. If all return expressions have a numeric datatype, then Oracle determines the argument with the highest numeric precedence, implicitly converts the remaining arguments to that datatype, and returns that datatype.
The return_expr
of a CASE
statement expects a single value so your sub-query:
( select value1 from test1 where department=t3.DEPARTMENT)
is what is raising the exception.
Instead use the filter on the sub-query:
select distinct t3.*
from test3 t3
INNER JOIN test1 t1
ON ( t3.department=t1.department )
WHERE t3.value1 not in (
select value1
from test1
where department=t3.DEPARTMENT
AND t1.CHECK_CONDITION1 = 1
)
Which, for your test data, outputs:
DEPARTMENT | VALUE1 | VALUE2 | VALUE3 ---------: | :----- | :----- | :------- 1 | Z | Y | Whatever
db<>fiddle here
Upvotes: 1
Reputation: 142705
That would be something like this, I presume:
SQL> select distinct t3.*
2 from test3 t3 join test1 t1 on t3.department=t1.department
3 where t3.value1 not in
4 (select t1.value1 from test1 t1
5 where t1.department = t3.department
6 and 1 = case when t1.check_condition1 = 1 then 1
7 else 0
8 end
9 );
DEPARTMENT VALUE1 VALUE2 VALUE3
---------- ---------- ---------- ----------
1 Z Y Whatever
SQL>
If condition was 0, you said you don't care, so:
SQL> update test1 set check_condition1 = 0;
2 rows updated.
SQL> select distinct t3.*
2 from test3 t3 join test1 t1 on t3.department=t1.department
3 where t3.value1 not in
4 (select t1.value1 from test1 t1
5 where t1.department = t3.department
6 and 1 = case when t1.check_condition1 = 1 then 1
7 else 0
8 end
9 );
DEPARTMENT VALUE1 VALUE2 VALUE3
---------- ---------- ---------- ----------
1 B Y Whatever
1 A T Whatever
1 Z Y Whatever
SQL>
Upvotes: 1