如何查询已全额支付的门票?SQL嵌套查询实现方案问询
查询所有已全额支付门票的SQL实现
针对你的需求,我提供两种实用的SQL写法,适配大部分主流关系型数据库(MySQL、PostgreSQL、SQL Server等),逻辑清晰且性能友好:
方法一:关联子查询(直观易懂)
这种写法直接在WHERE子句中对每个门票对应的booking进行总额校验,逻辑和你描述的伪SQL高度贴合:
SELECT t.* FROM tickets t WHERE ( -- 计算当前booking的总支付金额,无支付记录时返回0 SELECT COALESCE(SUM(p.amount), 0) FROM payments p WHERE p.booking_id = t.booking_id ) >= ( -- 计算当前booking的总门票价格 SELECT SUM(t2.price) FROM tickets t2 WHERE t2.booking_id = t.booking_id );
关键细节:
COALESCE(SUM(p.amount), 0):处理没有支付记录的booking(此时SUM返回NULL,直接对比会不成立,转为0后能正确识别未支付的情况)。- 每个ticket都会触发两次子查询,分别校验对应booking的支付总额是否≥门票总价,符合条件的门票才会被返回。
方法二:预聚合关联(性能更优)
如果数据量较大,重复子查询会影响效率,我们可以先通过CTE预计算所有符合条件的booking,再关联门票表:
WITH valid_bookings AS ( SELECT t.booking_id, SUM(t.price) AS total_ticket_cost, COALESCE(SUM(p.amount), 0) AS total_paid FROM tickets t LEFT JOIN payments p ON t.booking_id = p.booking_id GROUP BY t.booking_id -- 提前筛选出已全额支付的booking HAVING COALESCE(SUM(p.amount), 0) >= SUM(t.price) ) SELECT t.* FROM tickets t JOIN valid_bookings vb ON t.booking_id = vb.booking_id;
关键细节:
- 先通过
valid_bookingsCTE一次性计算所有booking的总额并筛选出符合条件的,避免重复计算。 - LEFT JOIN确保没有支付记录的booking也会被纳入计算(最终会被HAVING过滤)。
- 最后通过JOIN直接获取这些有效booking下的所有门票记录,性能比子查询更稳定。
额外提示
- 建议给
tickets.booking_id和payments.booking_id添加索引,能大幅提升聚合查询的速度。 - 如果你的数据库支持窗口函数,还可以用窗口函数简化写法,但上面两种方法兼容性更广,适合多数场景。
内容的提问来源于stack exchange,提问作者Sebastian Walker
相关产品推荐
相关产品推荐

