You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PostgreSQL中筛选每月均有至少1笔成功支付与1笔失败支付的用户

实现符合要求的用户筛选方案

嘿,这个需求核心是要验证用户的每一个有支付记录的月份,都同时存在成功和失败支付,我们可以通过两层聚合查询来实现,我给你详细拆解:

思路拆解

  1. 先按「用户+月份」分组,统计每个分组内是否同时存在成功(success=true)和失败(success=false)的支付;
  2. 再按「用户」分组,检查该用户的所有月份分组是否都满足「同时有成功和失败支付」的条件。

针对PostgreSQL的实现方案

如果你的数据库是PostgreSQL(支持BOOL_OR/BOOL_AND这类布尔聚合函数),可以用下面的高效写法:

SELECT user_id
FROM (
  -- 第一步:统计每个用户每个月份的支付状态覆盖情况
  SELECT
    user_id,
    date_trunc('month', paydate) AS pay_month,
    BOOL_OR(success) AS has_success,  -- 该月是否至少有1笔成功支付
    BOOL_OR(NOT success) AS has_failed  -- 该月是否至少有1笔失败支付
  FROM payments
  GROUP BY user_id, pay_month
) AS user_month_status
GROUP BY user_id
-- 第二步:验证该用户的所有月份都同时具备成功和失败支付
HAVING BOOL_AND(has_success AND has_failed) = TRUE

代码解释

  • 内层子查询user_month_status:用BOOL_OR快速判断每个用户的每个月份是否存在对应状态的支付(比COUNT更高效,找到第一个符合条件的记录就停止计算);
  • 外层查询的HAVING子句:BOOL_AND(has_success AND has_failed)会检查该用户的所有月份是否都同时满足「有成功且有失败」,只有全部满足的用户才会被筛选出来。

通用数据库兼容方案(比如MySQL)

如果你的数据库不支持布尔聚合函数,我们可以用COUNT(DISTINCT success)来判断状态覆盖情况:

SELECT user_id
FROM (
  SELECT
    user_id,
    DATE_FORMAT(paydate, '%Y-%m') AS pay_month,  -- MySQL的月份格式化方式,其他数据库可调整
    COUNT(DISTINCT success) AS status_type_count
  FROM payments
  GROUP BY user_id, pay_month
) AS user_month_status
GROUP BY user_id
-- 所有月份的状态类型数都必须是2(同时有true和false)
HAVING MIN(status_type_count) = 2

代码解释

  • 内层子查询统计每个用户每个月份的不同支付状态数量,如果等于2,说明该月同时有成功和失败支付;
  • 外层查询通过MIN(status_type_count) = 2确保该用户的所有月份都满足状态数为2,也就是每个月都同时有两种支付结果。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 23:27:33