You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Oracle SQL中关联三表获取所有子项已过期的A表记录方法

我来帮你搞定这个查询需求!先明确目标:我们要从A表中筛选出那些**所有关联到C表的child_id对应的expiration_date都早于当前系统时间(sysdate)**的记录——说白了就是某个ba_no下的所有子项全过期了,没有一个还在有效期内的。

先把已知的表结构和数据示例摆出来,方便对照:

表结构及数据示例

A表(ba_no, account)B表(ba_no, key_id)C表(key_id, child_id, expiration_date)sysdate
100, 1100, 2323, 1001, 28-apr-20sysdate
100, 1101, 2423, 1002, 28-apr-21sysdate
101, 2102, 2523, 1003, 28-apr-20sysdate
102, 324, 2000-sysdate
-24, 2052-sysdate
-25, 5201-sysdate

实现方案

这里给你两种常用的SQL写法,按需选择:

方法一:用NOT EXISTS排除存在有效子项的记录

这种方法的思路是:找到那些不存在任何关联到C表且expiration_date >= sysdate(未过期)的子项的ba_no,剩下的就是全过期的。

SELECT DISTINCT a.ba_no, a.account
FROM A a
JOIN B b ON a.ba_no = b.ba_no
-- 如果需要排除没有关联C表记录的ba_no,就保留下面的LEFT JOIN和WHERE条件;如果要包含无C表记录的,去掉即可
LEFT JOIN C c ON b.key_id = c.key_id
WHERE NOT EXISTS (
    SELECT 1
    FROM B b2
    JOIN C c2 ON b2.key_id = c2.key_id
    WHERE b2.ba_no = a.ba_no
      AND c2.expiration_date >= SYSDATE
)
AND c.key_id IS NOT NULL;

方法二:用GROUP BY + HAVING统计全过期的ba_no

这种方法更直接:先关联所有表,然后按A表的ba_no和account分组,判断该分组下所有C表的expiration_date的最大值都小于sysdate(也就是没有一个未过期的)。

SELECT a.ba_no, a.account
FROM A a
JOIN B b ON a.ba_no = b.ba_no
JOIN C c ON b.key_id = c.key_id
GROUP BY a.ba_no, a.account
HAVING MAX(c.expiration_date) < SYSDATE;

两种方法的区别

  • 方法一灵活度更高:可以轻松控制是否包含没有关联任何C表记录的ba_no(只要去掉AND c.key_id IS NOT NULL即可)。
  • 方法二逻辑更直观:适合确定要筛选的ba_no一定有对应C表记录的场景,执行效率通常也不错。

拿你的示例数据来说,如果sysdate是2024年的话,ba_no=100对应的C表记录过期日期都是2020和2021年,都早于sysdate,所以会被这两个查询选中;而ba_no=101、102要么没有对应C表记录,要么关联的B表key_id没有C表数据,方法二会直接过滤掉它们,方法一如果去掉那个条件会包含进来(取决于你的实际需求)。

内容的提问来源于stack exchange,提问作者Mudit B

火山引擎 最新活动