Skip to Main Content
  • Questions
  • Is there a better way to write this query?

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Philip.

Asked: February 21, 2007 - 2:29 pm UTC

Last updated: March 08, 2007 - 11:12 am UTC

Version: 9.2.0

Viewed 1000+ times

You Asked

I have the following two tables:

create table tab1(c1 number);

create table tab2(c2 number, c22 number);

insert into tab1 values(1);
insert into tab1 values(2);
insert into tab1 values(3);
insert into tab1 values(4);
insert into tab1 values(5);

insert into tab2 values(1, null);
insert into tab2 values(3, 1);
insert into tab2 values(4, null);
insert into tab2 values(4, 1);

Column c1 in table tab1 and c2 in table tab2 are the joining columns.

Note that there can be more than one record in table tab2 that matches a particular c1 value in table tab1.

I would like to see the following result when the two tables are joined:

C1 DATA_COLX
---- ----------
1 Y
2 N
3 N
4 Y
5 N

If there is at least one matching record in tab2 where c22 is null for a particular c1 value, a 'Y' is returned for column DATA_COLX.

If there is no matching record in tab2 for a particular c1 value, a 'N' is returned for column DATA_COLX.

If there are matching records in tab2 for a particular c1 value and c22 is not null, then return 'N' for column DATA_COLX.

The following query will produce the desired result:

select c1, 'Y' DATA_COLX from tab1
where exists (select 1 from tab2 where c2 = c1 and c22 is null)
union all
select c1, 'N' DATA_COLX from tab1
where not exists (select 1 from tab2
where c2 = c1)
union all
select c1, 'N' DATA_COLX from tab1
where exists (select 1 from tab2 a
where c2 = c1
and c22 is not null
and not exists (select 1 from tab2 b
where b.c2 = a.c2 and b.c22 is null))
order by c1

Can the result be achieved using a single SELECT statement?

Thank you for your help.
Philip




and Tom said...

ops$tkyte%ORA10GR2> select tab1.c1, decode( tab2.c2, NULL, 'N', 'Y' )
  2    from tab1,
  3        (select distinct c2 from tab2 where c22 is null) tab2
  4   where tab1.c1 = tab2.c2(+)
  5   order by tab1.c1
  6  /

        C1 D
---------- -
         1 Y
         2 N
         3 N
         4 Y
         5 N


the distinct is only needed if there is more than one record in tab2 for a given C2 value such that C22 is null

Rating

  (4 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

decode vs case

Livio, February 22, 2007 - 3:22 am UTC

Alternatively, we could replace decode with case:

select tab1.c1, case nvl(tab2.c2, -1) when -1 then 'N' else 'Y' end
from tab1,
(select distinct c2 from tab2 where c22 is null) tab2
where tab1.c1 = tab2.c2(+)
order by tab1.c1;
Tom Kyte
February 22, 2007 - 8:50 am UTC

alternatively you could do a better case


...
case when tab2.c2 is null then 'N' else 'Y' end
......

Philip Lee, February 22, 2007 - 1:18 pm UTC

Tom,

Thank you very much! It produced the same result as my original query but your query is much simpler and easier to maintain.

Inline view is very handy.

Thank You,
Philip

union query

A reader, March 08, 2007 - 10:19 am UTC

Tom,

Any suggestion on how to improve this query. Can I do better not using the union all.

SELECT TO_CHAR(response_ref_id),schedule_id,customer_id,mtn,campaign_id,
bill_account_number,owning_region_cd,response_status, response_sent_dt,
response_received_dt,response_received_code, validate_flag,
triggering_event_id,channel_id,channel_user_id,channel_location,
SELECTED_CHECKLIST_ITEM,SELECTED_OPTIONLIST_ITEM,delete_ind
FROM rm_response_e_sp a
UNION ALL
SELECT TO_CHAR(response_ref_id),
schedule_id,customer_id, mtn,campaign_id,bill_account_number, owning_region_cd,
response_status, response_sent_dt, response_received_dt,response_received_code,
validate_flag, triggering_event_id,channel_id, channel_user_id,
channel_location,SELECTED_CHECKLIST_ITEM,SELECTED_OPTIONLIST_ITEM,delete_ind
FROM rm_response_w_sp b
Tom Kyte
March 08, 2007 - 11:12 am UTC

looks awesome to me

I mean - well - you want all rows from two tables. It is about the simplest thing in the planet SQL wise. not too much you can do to such a simple query short of making it more complex!

YAHOOSTRONGERDRIVER

CiprianoCapote, February 10, 2014 - 2:22 am UTC

YSD@yahoostrongerdriver< http://www.yahoostronger.com/ysd is my.yahoo.com@ysd this my simplest address across to whole world I having trouble to my account<ciprianojr\Ciprianojrc@yaho.com was locked temporarily this account from https://twiter.com/ciprianojrc I needed your hand to helping me.