用单个列从另一个表更新一个表中的多个列?

Posted

技术标签:

【中文标题】用单个列从另一个表更新一个表中的多个列?【英文标题】:Updating several columns in one table from another table with a single column? 【发布时间】:2021-10-28 21:37:36 【问题描述】:

表 A 如下所示:

表 B 如下所示:

使用表 A 我需要在单行中更新表 B,并使用表 A 中的 DATETIME 列来获取表 B 中每一列的值(忽略表 B 单个记录中显示的状态)。所以从TABLE A的三条记录中,我只需要一条记录,并把与对应的STATUS匹配的日期,如果没有找到状态,把Table B中的日期放到:'2999-12-31 23 :59:5'

 when status = 'CLAIMED' put DATETIME in CLAIMED_DATETIME
 when status = 'BOUGHT' put DATETIME in BOUGHT_DATETIME
 when status = 'RETURNED' put DATETIME in RETURNED_DATETIME

我试过这个查询,但它只更新第一列,而不更新其余列。

UPDATE TABLE B a
SET
    CLAIMED_datetime = IFF(STATUS='claimed', DATETIME, '2999-12-31 23:59:5'),
    BOUGHT_datetime = IFF(STATUS='bought', DATETIME, '2999-12-31 23:59:5'),
    RETURNED_datetime = IFF(STATUS='returned', DATETIME, '2999-12-31 23:59:5'),
FROM TABLE A SRC
WHERE a.number_id = SRC.number_id
and a.country= SRC.country

我需要表 B 看起来像这样:

有谁知道查询出了什么问题或如何做到这一点?

【问题讨论】:

早上好,您尝试过使用 UNPIVOT 吗? docs.snowflake.com/en/sql-reference/constructs/unpivot.html 【参考方案1】:

只有第一个被更新的原因是因为一旦我们匹配了该行,它就不会再次更新,即使 JOIN 导致返回 3 行。第一行的状态为 CLAIMED,并且已更新,然后将忽略其余两个匹配的行。

正如 Patrick 提到的,我们可以尝试使用 PIVOT 函数将表 A 中的 3 行减少为一行,并在其自己的列上显示状态。

以下查询假设每个 number_id 和国家/地区只有一个 DATETIME 值:

create or replace table a (
    number_id int, country varchar, status varchar, datetime date
);
insert into a values 
(121144, 'USA', 'CLAIMED', '2021-10-10'),
(121144, 'USA', 'BOUGHT', '2021-10-11'),
(121144, 'USA', 'RETURNED', '2021-10-12'),
(121144, 'AU', 'CLAIMED', '2021-09-10'),
(121144, 'AU', 'BOUGHT', '2021-09-11');

create or replace table b (
    number_id int, country varchar, status varchar, 
    claimed_date date, bought_date date, returned_date date
);
insert into b values 
(121144, 'USA', 'RETURNED', '2999-12-31', '2999-12-31', '2999-12-31'),
(121144, 'AU', 'BOUGHT', '2999-12-31', '2999-12-31', '2999-12-31');



MERGE INTO B
USING (
    SELECT * FROM A 
    PIVOT(MIN(DATETIME) FOR STATUS IN ('CLAIMED', 'BOUGHT', 'RETURNED')) 
     AS P (NUMBER_ID, COUNTRY, CLAIMED, BOUGHT, RETURNED)
) A ON (A.NUMBER_ID = B.NUMBER_ID and A.COUNTRY = B.COUNTRY)
WHEN MATCHED THEN
  UPDATE SET
    B.CLAIMED_DATE = IFF(A.CLAIMED IS NOT NULL, A.CLAIMED, '2999-12-31 23:59:5'),
    B.BOUGHT_DATE = IFF(A.BOUGHT IS NOT NULL, A.BOUGHT, '2999-12-31 23:59:5'),
    B.RETURNED_DATE = IFF(A.RETURNED IS NOT NULL, A.RETURNED, '2999-12-31 23:59:5');

合并前:

+-----------+---------+----------+--------------+-------------+---------------+
| NUMBER_ID | COUNTRY | STATUS   | CLAIMED_DATE | BOUGHT_DATE | RETURNED_DATE |
|-----------+---------+----------+--------------+-------------+---------------|
|    121144 | USA     | RETURNED | 2999-12-31   | 2999-12-31  | 2999-12-31    |
|    121144 | AU      | BOUGHT   | 2999-12-31   | 2999-12-31  | 2999-12-31    |
+-----------+---------+----------+--------------+-------------+---------------+

合并后:

+-----------+---------+----------+--------------+-------------+---------------+
| NUMBER_ID | COUNTRY | STATUS   | CLAIMED_DATE | BOUGHT_DATE | RETURNED_DATE |
|-----------+---------+----------+--------------+-------------+---------------|
|    121144 | USA     | RETURNED | 2021-10-10   | 2021-10-11  | 2021-10-12    |
|    121144 | AU      | BOUGHT   | 2021-09-10   | 2021-09-11  | 2999-12-31    |
+-----------+---------+----------+--------------+-------------+---------------+

如果状态是固定的,即只有 CLAIMED、BOUGHT 和 RETURNED 的值,也许您可​​以重新设计您的表格以将它们放入列中?

【讨论】:

以上是关于用单个列从另一个表更新一个表中的多个列?的主要内容,如果未能解决你的问题,请参考以下文章

如何在子查询中使用外部查询中的列从另一个表中获取结果?

Spark 从另一个表更新 Delta 中的多个列

使用 MSSQL 中的 DYNAMIC SQL 从另一个表更新一个表中的值

SQL 从另一个表中的另一列更新一列

从另一个表中复制 IDENTITY 列并为丢失的记录生成新的 ID

Excel:如何根据键列从另一个工作表添加列?