You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SQL将表A现有列填充为表B对应列的首个匹配值?

问题描述

现有表A,包含主键列id和contact_name列,该列所有值目前均为NULL。另有表B,包含contact_name列和ref_id列,B表的ref_id与A表的id一一对应,但B表中可能存在多个ref_id相同的行。

示例数据:
表A(初始状态)

id | contact_name
1  | NULL
2  | NULL

表B

ref_id | contact_name
1      | "John"
2      | "Helen"
2      | "Alex"

要求:在不新增或修改两表其他行的前提下,将表A的contact_name列填充为B表中对应ref_id匹配的首个contact_name值,最终表A结果如下:

id | contact_name
1  | "John"
2  | "Helen"
解决方案

1. MySQL(8.0+ 支持窗口函数)

使用ROW_NUMBER()窗口函数为每个ref_id的行排序,取排序后的第一行数据更新表A:

UPDATE tableA a
JOIN (
    SELECT 
        ref_id,
        contact_name,
        ROW_NUMBER() OVER (PARTITION BY ref_id ORDER BY (SELECT 0)) AS rn
    FROM tableB
) b ON a.id = b.ref_id AND b.rn = 1
SET a.contact_name = b.contact_name;

注:ORDER BY (SELECT 0)是利用MySQL特性,不指定具体排序字段时按数据存储的物理顺序取第一行;若有明确排序规则(如按创建时间),可替换为对应字段,比如ORDER BY create_time ASC。

2. PostgreSQL

通过窗口函数筛选每个ref_id的首行,再关联更新:

UPDATE tableA a
SET contact_name = b.contact_name
FROM (
    SELECT 
        ref_id,
        contact_name,
        ROW_NUMBER() OVER (PARTITION BY ref_id ORDER BY ctid) AS rn
    FROM tableB
) b
WHERE a.id = b.ref_id AND b.rn = 1;

注:ctid是PostgreSQL标识行物理位置的系统字段,用来取存储顺序的第一行,也可替换为业务排序字段。

3. SQL Server

方法一:窗口函数

UPDATE a
SET a.contact_name = b.contact_name
FROM tableA a
INNER JOIN (
    SELECT 
        ref_id,
        contact_name,
        ROW_NUMBER() OVER (PARTITION BY ref_id ORDER BY (SELECT NULL)) AS rn
    FROM tableB
) b ON a.id = b.ref_id AND b.rn = 1;

方法二:TOP 1 WITH TIES

UPDATE a
SET a.contact_name = b.contact_name
FROM tableA a
INNER JOIN (
    SELECT TOP 1 WITH TIES
        ref_id,
        contact_name
    FROM tableB
    ORDER BY ROW_NUMBER() OVER (PARTITION BY ref_id ORDER BY (SELECT NULL))
) b ON a.id = b.ref_id;

4. Oracle

使用MERGE结合窗口函数实现更新:

MERGE INTO tableA a
USING (
    SELECT 
        ref_id,
        contact_name,
        ROW_NUMBER() OVER (PARTITION BY ref_id ORDER BY ROWID) AS rn
    FROM tableB
) b
ON (a.id = b.ref_id AND b.rn = 1)
WHEN MATCHED THEN UPDATE SET a.contact_name = b.contact_name;

注:ROWID是Oracle中行的唯一物理标识符,用来取存储顺序的第一行,也可替换为业务排序字段。

内容的提问来源于stack exchange,提问作者Patrick Abbey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 05:25:24