I'm doing a query across databases with an identical structure, to show a mapping from a source value to a target value.
Every one of my databases has a table with two columns: source and target
DB1
Source | Target |
---|---|
A | X |
A | Y |
B | NULL |
C | NULL |
DB2
Source | Target |
---|---|
A | NULL |
A | Y |
B | Z |
So my query is
Select t.Source, t.Target
from DB1.table t
union
Select t.Source, t.Target
from DB2.table t
What I'm getting is
Source | Target |
---|---|
A | X |
A | Y |
B | NULL |
C | NULL |
B | Z |
A | NULL |
But I'm only interested in the target being NULL, if there is no other mapping present. So I'm looking for the following result:
Source | Target |
---|---|
A | X |
A | Y |
C | NULL |
B | Z |
How can I easily eliminate the highlighted rows A | NULL
and B | NULL
from my results?
I've seen a few answers suggesting using MAX(Target)
, but that won't work for me since I can have multiple valid mappings for a single source (A | X
and A | Y
)
CodePudding user response:
Something like this would work, just give a number based on NULL, and select the first:
SELECT TOP(1) WITH TIES UN.Source
, UN.Target
FROM (
Select t.Source, t.Target
from DB1.table t
union
Select t.Source, t.Target
from DB2.table t
) AS UN
ORDER BY DENSE_RANK()OVER(PARTITION BY UN.Source ORDER BY CASE WHEN UN.Target IS NOT NULL THEN 1 ELSE 2 END)
CodePudding user response:
You might find it easier to think in terms of minimums:
with data as (
select Source, Target from DB1.<table> union
select Source, Target from DB2.<table>
), qualified as (
select *,
case when Target is not null or min(Target) over (partition by Source) is null
then 1 end as Keep
from data
)
select Source, Target from qualified where Keep = 1;