SQL双表查询:获取Table A符合日期条件或无匹配名的最新数据
SQL需求及问题解决
需求说明
现有Table A和Table B两张表,需针对每个name执行以下逻辑:仅当Table A中该name的最新数据日期晚于Table B中该name的最新日期,或该name不存在于Table B时,获取Table A中该name的最新数据。
原SQL语句(未得到预期结果)
SELECT t1.* FROM table_a t1 WHERE t1.date > (SELECT MAX(t2.date) FROM table_b t2 WHERE t1.name = t2.name) ORDER BY t1.date DESC LIMIT 1
数据表内容
Table A 数据
| id | name | date | state | age |
|---|---|---|---|---|
| 1 | John | 2022-11-25 05:02:55 | NY | 32 |
| 2 | Mary | 2022-11-28 08:05:55 | HI | 26 |
| 3 | Mary | 2022-11-25 01:02:54 | FL | 25 |
| 4 | Bill | 2022-11-28 05:02:35 | NY | 32 |
| 5 | Bill | 2022-11-15 05:02:55 | HI | 26 |
| 6 | Bill | 2022-11-11 07:33:21 | FL | 25 |
Table B 数据
| id | name | date | college | weight |
|---|---|---|---|---|
| 1 | John | 2022-11-26 05:02:55 | NYU | 180 |
| 2 | Mary | 2022-11-27 05:02:55 | HIU | 140 |
| 3 | Mary | 2022-11-25 05:02:55 | FLU | 155 |
预期结果
| id | name | date | state | age |
|---|---|---|---|---|
| 2 | Mary | 2022-11-28 08:05:55 | HI | 26 |
| 4 | Bill | 2022-11-28 05:02:35 | NY | 32 |
原SQL问题分析
- 未处理name不存在于Table B的场景:当name在Table B中无匹配时,子查询返回
NULL,而t1.date > NULL的逻辑判断结果为UNKNOWN,无法选中该行,导致Bill的数据无法被取出。 - 结果行数限制错误:末尾的
LIMIT 1强制只返回一行,但需求是返回所有符合条件的name的最新数据。 - 未筛选每个name的最新数据:原SQL仅筛选出Table A中日期大于对应Table B最大日期的行,但没有确保取的是每个name的最新那条记录。
正确SQL实现
WITH a_latest AS ( -- 获取Table A中每个name的最新数据 SELECT * FROM table_a t1 WHERE NOT EXISTS ( SELECT 1 FROM table_a t2 WHERE t2.name = t1.name AND t2.date > t1.date ) ), b_latest AS ( -- 计算Table B中每个name的最新日期 SELECT name, MAX(date) AS max_date FROM table_b GROUP BY name ) -- 筛选符合条件的记录 SELECT a_latest.* FROM a_latest LEFT JOIN b_latest ON a_latest.name = b_latest.name WHERE b_latest.max_date IS NULL -- name不存在于Table B OR a_latest.date > b_latest.max_date; -- Table A最新日期晚于Table B
逻辑说明
a_latestCTE:通过排除同name下日期更大的记录,得到每个name在Table A中的最新数据。b_latestCTE:按name分组聚合,得到每个name在Table B中的最新日期。- 主查询:左连接两个CTE,筛选出两种符合需求的场景,最终得到预期结果。
内容的提问来源于stack exchange,提问作者Altitude
相关产品推荐
相关产品推荐

