views:

37

answers:

3

Hi

Based on the below tables

Table_A

Id  RelatedId
---------------
1   1
1   2
1   3
2   4
2   5
2   2
3   7
3   8
4   9

Table_B

RelatedId  Name
--------------
2          A
3          B

I want to get all the rows from Table_A which have atleast one matching relatedid in Table_B. The Ids from Table_A that do not have match in Table_B will have single row in the result table.

So output (result table) in this case will be

Id  RelatedId
---------------
1   1
1   2
1   3
2   4
2   5
2   2
3   Null
4   Null

Thanks

EDIT: Seems like the question text is confusing for many. So a detailed explanation:

Table_A Id 1 has both 2 and 3 (Related Ids) matching in table_B. So output will have all the rows for 1 from Table_A. Similary Id 2 from Table_A has 2 (Related Id) matching in table_B. So all rows corresponding to 2 from Table_A will be picked up. Since 3 does not have any matching relatedid in table_B it will be displayed but with NULL as relatedid in the results table.

+2  A: 

Try:

  Select Distinct Id, Related_Id
  From Table_A 
  Where Related_Id In 
      (Select Related_Id From Table_B) 
Charles Bretana
+1 for typing faster than me :)
Ray
@Charles: The above does not give the desired result. I think i was not clear with my explanation. The output has has to have all rows from Table_A if that particular Id has atleast one matching RelatedId in Table_B. So in this case from Table_A Id 1 has both 2 and 3 matching in table_B. So output will have all the rows for 1 from Table_A. Similary Id 2 from Table_A has 2 matching in table_B. So all rows corresponding to 2 from Table_A will be picked up. Since 3 does not have any matching relatedid in table_B it will be displayed but with NULL as relatedid in the results table.
stackoverflowuser
ahh, that was not clear... I will edit to correct.. As you have just articulated it, all you want is the rows from Table_A where the Related ID is in Table_B? Then the amended sql should do the trick
Charles Bretana
@Charles: Actually its not giving the intended result. Can you pls. let me know what is the alias "B" corresponding to in the above query ??
stackoverflowuser
'twas typo I needed to delete from editing the first sql, which I failed to delete... should work now..
Charles Bretana
+3  A: 
with validids as (
 select distinct id 
 from Table_A 
  inner join Table_B on 
   Table_A.relatedid = Table_B.relatedid
)
select 
  id,
  relatedid
from Table_A 
where id in (select id from validids)
union 
select distinct
 id, 
 null
from Table_A
where id not in (select id from validids)
Chris Simpson
This is more than just an outer join issue. The results include more information than what would be displayed by a standard outer join.
bobs
yeah, that was my original answer which I undeleted so I could put the real answer in. unfortunately you could all see the answer again whilst I edited it.
Chris Simpson
any chance of retracting the -1
Chris Simpson
Nice recovery. I like the new answer. Sorry, I pulled the -1 trigger. I'll give it back where I can. There you go, 2-point switch. :)
bobs
haha, thank you
Chris Simpson
@Chris: Thanks. That gives the desired output. +1 and green check :)
stackoverflowuser
+1  A: 

This should do what you want:

with IdsWithMatchInB(Id) as (
  select distinct
    Id
  from Table_A
  where Table_A.RelatedId in (
    select Table_B.RelatedId
    from Table_B
  )
)
  select
    Table_A.Id,
    CASE WHEN IdsWithMatchInB.Id IS NULL
         THEN NULL
    ELSE Table_A.RelatedId END AS RelatedId
from Table_A
left outer join IdsWithMatchInB
on IdsWithMatchInB.Id = Table_A.Id

Here's another option that avoids DISTINCT by putting the subquery inside the CASE expression:

select
  Id,
  case when Id in (
    select Id
    from Table_A as Acopy
    where Acopy.RelatedId in (
      select
        RelatedId 
      from Table_B
    )
  )
  then RelatedId
  else null end as RelatedId
from Table_A;

One or the other might be more efficient for your particular data and indexes.

Steve Kass