MySQL查询30天内需开票企业:新增发票后旧记录未移除
我明白你的问题了——当你给企业开了一张远期(12个月后到期)的新发票时,系统仍然会把该企业旧的、30天内到期的发票列出来,这显然不是你想要的结果。你需要的是:如果企业已经有了一张更新的发票(不管到期日多远),就排除它所有旧的到期发票;只保留那些没有更新发票、且当前有发票在30天内到期的企业记录,或者说只保留每个企业最新的、且在30天内到期的发票记录。
下面给你两种可行的解决方案,适配不同版本的数据库:
方案1:使用窗口函数(推荐,适用于MySQL 8+、PostgreSQL等现代数据库)
利用ROW_NUMBER()窗口函数给每个企业的发票按到期日倒序排序,只保留每个企业的最新发票,再筛选这张发票是否在目标时间范围内:
SELECT * FROM ( SELECT P.*, I.*, -- 按企业分组,发票到期日越晚,排序号越小(最新的发票rn=1) ROW_NUMBER() OVER (PARTITION BY P.PRAC_ID ORDER BY I.NEXT_DUE DESC) AS rn FROM SW_PRACTICES AS P JOIN SW_INVOICES AS I ON P.PRAC_ID = I.PRAC_ID WHERE P.ACTIVE = '2' ) AS sub_query -- 只保留每个企业的最新发票,且该发票到期日在指定范围内 WHERE rn = 1 AND NEXT_DUE > NOW() - INTERVAL 7 DAY AND NEXT_DUE < NOW() + INTERVAL 30 DAY ORDER BY INV_ID ASC;
方案2:使用子查询找最新到期日(适用于不支持窗口函数的旧版数据库,如MySQL 5.x)
先通过子查询获取每个企业的最新发票到期日,再关联回原表筛选符合条件的记录:
SELECT P.*, I.* FROM SW_PRACTICES AS P JOIN SW_INVOICES AS I ON P.PRAC_ID = I.PRAC_ID -- 子查询获取每个企业的最新发票到期日 JOIN ( SELECT PRAC_ID, MAX(NEXT_DUE) AS latest_due_date FROM SW_INVOICES GROUP BY PRAC_ID ) AS latest_invoices ON I.PRAC_ID = latest_invoices.PRAC_ID AND I.NEXT_DUE = latest_invoices.latest_due_date WHERE P.ACTIVE = '2' AND I.NEXT_DUE > NOW() - INTERVAL 7 DAY AND I.NEXT_DUE < NOW() + INTERVAL 30 DAY ORDER BY I.INV_ID ASC;
两种方案的核心逻辑一致:只关注每个企业的最新发票,如果这张最新发票的到期日在你设定的30天范围内,就保留该记录;如果企业已经有了远期的新发票,这张发票的到期日不在目标范围内,整个企业的记录会被自动排除,旧发票也不会出现在结果里。
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

