简体   繁体   中英

Replace nulls of a column with column value from another table

I have data flowing from two tables, table A and table B. I'm doing an inner join on a common column from both the tables and creating two more new columns based on different conditions. Below is a sample dataset:

Table A

| Id  | StartDate  |
|-----|------------|
| 119 | 01-01-2018 |
| 120 | 01-02-2019 |
| 121 | 03-05-2018 |
| 123 | 05-08-2021 |

TABLE B

| Id  | CodeId | Code | RedemptionDate |
|-----|--------|------|----------------|
| 119 | 1      | abc  | null           |
| 119 | 2      | abc  | null           |
| 119 | 3      | def  | null           |
| 119 | 4      | def  | 2/3/2019       |  
| 120 | 5      | ghi  | 04/7/2018      |
| 120 | 6      | ghi  | 4/5/2018       |
| 121 | 7      | jkl  | null           |
| 121 | 8      | jkl  | 4/4/2019       |
| 121 | 9      | mno  | 3/18/2020      |
| 123 | 10     | pqr  | null           |

What I'm basically doing is joining the tables on column 'Id' when StartDate>2018 and create two new columns - 'unlock' by counting CodeId when RedemptionDate is null and 'Redeem' by counting CodeId when RedmeptionDate is not null. Below is the SQL query:

WITH cte1 AS (
    SELECT a.id, COUNT(b.CodeId) AS 'Unlock'  
    FROM TableA AS a
    JOIN TableB AS b ON a.Id=b.Id
    WHERE YEAR(a.StartDate) >= 2018 AND b.RedemptionDate IS NULL
    GROUP BY a.id
), cte2 AS (
    SELECT a.id, COUNT(b.CodeId) AS 'Redeem'  
    FROM TableA AS a
    JOIN TableB AS b ON a.Id=b.Id
    WHERE YEAR(a.StartDate) >= 2018 AND b.RedemptionDate IS NOT NULL
    GROUP BY a.id
)
SELECT cte1.Id, cte1.Unlocked, cte2.Redeemed
FROM cte1
FULL OUTER JOIN cte2 ON cte1.Id = cte2.Id

If I break down the output of this query, result from cte1 will look like below:

| Id  | Unlock |
|-----|--------|
| 119 | 3      |
| 121 | 1      |
| 123 | 1      |

And from cte2 will look like below:

| Id  | Redeem |
|-----|--------|
| 119 | 1      |
| 120 | 2      |
| 121 | 2      |

The last select query will produce the following result:

| Id   | Unlock | Redeem |
|------|--------|--------|
| 119  | 3      | 1      |
| null | null   | 2      |
| 121  | 1      | 2      |
| 123  | 1      | null   |

How can I replace the null value from Id with values from 'b.Id'? If I try coalesce or a case statement, they create new columns. I don't want to create additional columns, rather replace the null values from the column values coming from another table. My final output should like:

| Id  | Unlock | Redeem |
|-----|--------|--------|
| 119 | 3      | 1      |
| 120 | null   | 2      |
| 121 | 1      | 2      |
| 123 | 1      | null   |

If I'm following correctly, you can use apply with aggregation:

select a.*, b.*
from a cross apply
     (select count(RedemptionDate) as num_redeemed,
             count(*) - count(RedemptionDate) as num_unlock
      from b
      where b.id = a.id
     ) b;

However, the answer to your question is to use coalesce(cte1.id, cte2.id) as id .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM