编写SQL查询获取仅满足Invoice_Date晚于C_Start_Date的ID
筛选所有发票日期均晚于起始日期的ID方案
先明确下题目里的测试数据:
Table A(记录每个ID的起始日期)
| ID | C_Start_Date |
|---|---|
| 1 | 2018-03-10 |
| 2 | 2018-03-15 |
Table B(记录每个ID的发票日期)
| ID | Invoice_Date |
|---|---|
| 1 | 2018-01-15 |
| 1 | 2018-02-15 |
| 1 | 2018-03-15 |
| 2 | 2018-04-01 |
| 2 | 2018-04-04 |
我们的目标是找出所有关联发票日期都晚于对应起始日期的ID——就像示例里的ID=2,而ID=1因为存在早于起始日期的发票,需要被排除。
下面分享几种实用的实现方式:
方法一:NOT EXISTS子查询(最直观)
核心思路:找出那些不存在任何发票日期≤起始日期的ID。
SELECT DISTINCT a.ID FROM TableA a WHERE NOT EXISTS ( SELECT 1 FROM TableB b WHERE b.ID = a.ID AND b.Invoice_Date <= a.C_Start_Date );
逻辑说明
遍历TableA的每个ID,检查TableB中是否存在该ID的发票日期不晚于起始日期的记录。如果完全没有这样的记录,就保留这个ID。DISTINCT是为了兼容TableA存在重复ID的场景(示例里没有,但实际业务中可能出现)。
方法二:GROUP BY + HAVING(从聚合角度出发)
思路是先分组,再判断组内最早的发票日期是否晚于起始日期——只要最早的都晚,那所有发票肯定都符合要求。
SELECT b.ID FROM TableB b JOIN TableA a ON b.ID = a.ID GROUP BY b.ID, a.C_Start_Date HAVING MIN(b.Invoice_Date) > a.C_Start_Date;
逻辑说明
把两个表关联后,按ID和对应的起始日期分组,用MIN(b.Invoice_Date)拿到该ID最早的发票日期,只要这个日期晚于起始日期,就说明该ID的所有发票都满足条件。
方法三:LEFT JOIN + IS NULL(反匹配思路)
和NOT EXISTS逻辑类似,通过左连接找到不符合条件的ID,再排除它们。
SELECT DISTINCT a.ID FROM TableA a LEFT JOIN TableB b ON a.ID = b.ID AND b.Invoice_Date <= a.C_Start_Date WHERE b.ID IS NULL;
逻辑说明
左连接后,那些没有匹配到“发票日期≤起始日期”记录的ID,对应的b.ID字段会是NULL,这些就是我们要找的目标ID。
这几种方法在不同数据库中的性能表现可能略有不同,但核心逻辑一致,你可以根据自己的业务场景和数据库特性选择最合适的写法~
内容的提问来源于stack exchange,提问作者Anshul Dahiya
相关产品推荐
相关产品推荐

