用另一个表中的列值替换列的空值

Posted

技术标签:

【中文标题】用另一个表中的列值替换列的空值【英文标题】:Replace nulls of a column with column value from another table 【发布时间】:2021-06-16 11:05:12 【问题描述】:

我的数据来自两个表,表 A 和表 B。我正在对两个表中的一个公共列进行内部联接,并根据不同的条件创建另外两个新列。下面是一个示例数据集:

表 A

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

表 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           |

我基本上在做的是在 StartDate>2018 时加入“Id”列上的表并创建两个新列 - 当 RedemptionDate 为空时通过计数 CodeId 来“解锁”,当 RedmeptionDate 不为空时通过计数 CodeId 来“赎回” .下面是 SQL 查询:

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

如果我分解此查询的输出,来自 cte1 的结果将如下所示:

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

从 cte2 开始,如下所示:

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

最后一个选择查询将产生以下结果:

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

如何将 Id 中的空值替换为“b.Id”中的值?如果我尝试合并或 case 语句,它们会创建新列。我不想创建额外的列,而是替换来自另一个表的列值中的空值。 我的最终输出应该是:

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

【问题讨论】:

已编辑 - 这是 SQL Server 所以SELECT coalesce(cte1.Id,cte2.Id) 不起作用?如果您可以创建一个小提琴,那就太好了,因为我不打算输入您的所有数据。我强烈建议您也使用您的 SQL 布局......当它像这样的文字墙时很难理解。 【参考方案1】:

如果我没看错,你可以使用 apply 和聚合:

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;

但是,您的问题的答案是使用coalesce(cte1.id, cte2.id) as id

【讨论】:

以上是关于用另一个表中的列值替换列的空值的主要内容,如果未能解决你的问题,请参考以下文章

如何从 sqlite 游标中获取列值?

如何在 BigQuery 中将多个列的空值替换为 0?

SQL触发器用INSERT上的当前日期替换表中的空值?

用另一个表中同一列的值替换列中的字符串值

如何在熊猫数据框中仅填充选定列的空值? [复制]

数据清洗--DataFrame中的空值处理