SQL进阶技巧 | 如何取多个表中某一字段不为空且时间最新的值?

0 问题描述

问题:如何取多个表中某一字段不为空且时间最新的值?

举个例子,多张表(其中人会有重复)中都有电话号码这个字段,我需要取每个人最新的电话号码。

表1,命名为t1

name

contact_phone

update_time

王二

111

2019

张三

123

2019

李四

642

2020

表2,命名为t2

name

contact_phone

update_time

王二

222

2022

张三

NULL

2021

李四

753

2010

表3,命名为t3

name

contact_phone

update_time

张三

789

2012

李四

864

2021

最后需要的结果为

name

contact_phone

update_time

王二

222

2022

张三

123

2019

李四

864

2021

1 数据准备

-- 创建表 t1
CREATE TABLE t1 (
name STRING,
contact_phone STRING,
update_time INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';  
-- 创建表 t2
CREATE TABLE t2 (
name STRING,
contact_phone STRING,
update_time INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';

-- 创建表 t3
CREATE TABLE t3 (
name STRING,
contact_phone STRING,
update_time INT
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';

-- 插入 t1 数据
truncate table t1 ;
INSERT INTO t1 VALUES
('王二',   '111', 2019),
('张三',   '123', 2019),
('李四',   '642', 2020);

-- 插入 t2 数据
truncate table t2 ;
INSERT INTO t2 VALUES
('王二', '222',   2022),
('张三', NULL,    2021),  
('李四', '753',   2010);

-- 插入 t3 数据
INSERT INTO t3 VALUES
('张三', '789', 2012),
('李四', '864', 2021);

2 问题分析

将三张表合并,形成原始数据表​​​​​​

select * from t1union allselect * from t2union allselect * from t3

组内取最新时间点对应的值,我们一般用row_number()或first_value()函数,但如果直接使用分析函数会导致张三这一组数据取到最新的值为NULL,明显是不符合题意的,题目要求为字段不为NULL且最新。

方法1:利用order by nulls last特性求解

with temp as

(

  select

    a.*,

    row_number() over(partition by name order by concat(update_time,contact_phone) desc nulls last) as rn

  from

  (

    select * from t1

    union all

    select * from t2

    union all

    select * from t3

  )a

)

select name

     , contact_phone

     , update_time

from temp where rn=1

方法2:底表直接过滤掉非法数据,然后使用row_number()函数​​​​​​​

SELECT  name,  contact_phone,  update_timeFROM (  SELECT    name,    contact_phone,    update_time,    ROW_NUMBER() OVER (      PARTITION BY name      ORDER BY update_time DESC    ) AS rn  FROM (    -- 合并所有表并过滤空值    SELECT name, contact_phone, update_time    FROM t1    WHERE contact_phone IS NOT NULL    UNION ALL    SELECT name, contact_phone, update_time    FROM t2    WHERE contact_phone IS NOT NULL    UNION ALL    SELECT name, contact_phone, update_time    FROM t3    WHERE contact_phone IS NOT NULL  ) combined_data) ranked_dataWHERE rn = 1;

方法3:通过关联形式求解

with data as (    -- 合并所有表并过滤空值    SELECT name, contact_phone, update_time    FROM t1    WHERE contact_phone IS NOT NULL    UNION ALL    SELECT name, contact_phone, update_time    FROM t2    WHERE contact_phone IS NOT NULL    UNION ALL    SELECT name, contact_phone, update_time    FROM t3    WHERE contact_phone IS NOT NULL)select  t1.name      , t1.contact_phone      , t1.update_timefrom data t1    join (select name, max(update_time) update_timefrom datagroup by name ) t2on t1.name = t2.name and t1.update_time = t2.update_time

3 小结

通过上述方法,可高效解决多表合并、非空筛选与最新记录选取问题。核心在于:

  • 数据清洗

    严格过滤无效值;

  • 排序控制 

    利用窗口函数和次级字段保证结果唯一性;

  • NULL 处理 

    根据 Hive 版本选择 NULLS LAST 或 CASE 表达式显式控制排序逻辑;

  • 类型安全 

    确保时间字段正确排序。

这些方法不仅适用于电话号码场景,还可推广至订单状态更新、用户行为日志等需提取最新有效记录的典型应用。

🚀 「SQL进阶实战技巧」专栏重磅上线! 🚀

🌟 从零到高手,解锁SQL的无限可能! 🌟

这里有SQL的终极进阶秘籍:

 ✅ 正则表达式精准提取数据、✅ Window函数玩转复杂分析、✅ Bitmap优化提速百倍查询
✅ 缺失值补全、✅ 分钟级趋势预测、✅ 非线性回归建模、✅ 逻辑推理破题、✅ 波峰智能检测

🛠️ 给数据工程师的超强工具箱:
👉 解决「电梯超载难题」👉 预测「商品零售增长」
👉 跳过「NULL值天坑」👉 拆解「JSON密钥迷宫」
👉 巧算「连续签到金币」👉 嗨翻「赛马趣味逻辑」 

🔥 突破常规,用SQL实现Python级分析!
从线性回归到指数平滑预测,从块熵计算到TEO能量检测——原来SQL才是隐藏的科学计算利器!

📈 无论你是想优化千万级数据性能,还是用一句SQL破解公务员考题,这里都有答案!

🦅 让SQL飞越数据的天空,带你用代码写出商业洞见!
👉 点击探索,开启你的数据分析新次元!

👉专栏链接如下:

数字化建设通关指南_莫叫石榴姐的博客-CSDN博客

SQL进阶实战技巧_莫叫石榴姐的博客-CSDN博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值