Reputation: 6410
I have three tables like below:
Test
+--------------+--------+
| Test_Case_ID | Status |
+--------------+--------+
| 10 | PASS |
| 20 | FAIL |
| 30 | FAIL |
+--------------+--------+
Defect
+-----------+
| Defect_ID |
+-----------+
| 500 |
| 400 |
+-----------+
and link1
+--------------+-----------+
| Test_Case_ID | Defect_ID |
+--------------+-----------+
| 20 | 500 |
| 30 | 500 |
| 30 | 400 |
+--------------+-----------+
I am trying the below query
select
test.test_case_id,
test.status,
case when test.status = 'FAIL' then
(select link1.defect_id
from link1
where
test.test_case_id = link1.test_case_id)
end as defect1_id
from test test
I get the below error "Error 12/20/2012 10:05:17 AM 0:00:00.093 Toad for Data Analysts: ORA-01427: single-row subquery returns more than one row 1 78 "
Is there a way to retrieve both the records for "30" from the link table? Because i want to display that test case 30 is failing because of defect 500 & 400.
Thanks so much
Upvotes: 4
Views: 17979
Reputation: 247670
Have you thought about using a JOIN
instead of the subquery:
select
t.test_case_id,
t.status,
case when t.status = 'FAIL' then l.defect_id
end as defect1_id
from test t
left join link1 l
on t.test_case_id = l.test_case_id
This will return both records, then you can decide which item to return in your final result.
Result:
| TEST_CASE_ID | STATUS | DEFECT1_ID |
--------------------------------------
| 20 | FAIL | 500 |
| 30 | FAIL | 500 |
| 30 | FAIL | 400 |
| 10 | PASS | (null) |
Based on your comment, if you are using Oracle 11g, then you can use the LISTAGG()
function to combine the records into one row:
select
t.test_case_id,
t.status,
case
when t.status = 'FAIL'
then listagg(l.defect_id, ', ')
within group (order by l.defect_id)
end as defect1_id
from test t
left join link1 l
on t.test_case_id = l.test_case_id
group by t.test_case_id, t.status
Result:
| TEST_CASE_ID | STATUS | DEFECT1_ID |
--------------------------------------
| 10 | PASS | (null) |
| 20 | FAIL | 500 |
| 30 | FAIL | 400, 500 |
Upvotes: 3
Reputation: 1269583
You have two rows in the link table that have values of "30". This is your problem.
Which of these rows do you want?
To fix the subquery, you can either say select max(link1.defect_id)
or add and rownum = 1
to the where
clause.
What you want is probably a bi more complicated. How about this version, which concatenates the defects into a string:
select t.test_case_id, t.status,
listagg(cast(l.defect_id as varchar(32)) within group (order by l.defect_id) as defects
from test t left join
link1 l
on t.test_case_id = l.test_case_id
group by t.test_case_id, t.status
You don't specify the version of Oracle. If listagg
is not available, then wm_concat
probably is. Here is a reference on different ways to concat strings in an aggregation in Oracle.
Upvotes: 4