分组依据-按每月符合的条件进行选择

时间:2018-11-24 16:11:38

标签: sql postgresql

以下查询返回给定月份中具有USERS的所有SUM(AMOUNT) > 10。即使一个月内的用户不符合标准,它也会包含一个月内的用户。

但是我想将此查询转换为必须满足条件USERS的所有SUM(AMOUNT) > 10,每个月(即从表中的第一个月到最后一个月) )。

采用另一种方式,排除每个月不符合SUM(AMOUNT) > 10的用户。

select USERS, to_char(transaction_date, 'YYYY-MM') as month
from Table
GROUP BY USERS, month
HAVING SUM(AMOUNT) > 10;

4 个答案:

答案 0 :(得分:0)

一种方法是使用生成的日历表代表数据集中的所有月份。我们可以将此日历表保留到您当前的查询中,然后按用户汇总所有月份:

WITH months AS (
    SELECT DISTINCT TO_CHAR(transaction_date, 'YYYY-MM') AS month
    FROM yourTable
),
cte AS (
    SELECT USERS, TO_CHAR(transaction_date, 'YYYY-MM') AS month
    FROM yourTable
    GROUP BY USERS, month
    HAVING SUM(AMOUNT) > 10
)

SELECT
    t.USERS
FROM months m
LEFT JOIN cte t
    ON m.month = t.month
GROUP BY
    t.USERS
HAVING
    COUNT(t.USERS) = (SELECT COUNT(*) FROM months);

上面的HAVING子句断言,用户匹配的月数实际上是月总数。这意味着用户符合每月的总计标准。

答案 1 :(得分:0)

一个选择是使用sign(amount-10)sign(amount)逻辑作为

SELECT q.users
  FROM
    (
    with tab(users, transaction_date,amount) as
    (
     select 1,date'2018-11-24',8 union all
     select 1,date'2018-11-24',18 union all    
     select 2,date'2018-10-24',13 union all
     select 3,date'2018-11-24',18 union all    
     select 3,date'2018-10-24',28 union all
     select 3,date'2018-09-24', 3 union all    
     select 4,date'2018-10-24',28
    )
    SELECT users, to_char(transaction_date, 'YYYY-MM') as month, 
           sum(sign(amount-10)) as cnt1,
           sum(sign(amount)) as cnt2
      FROM tab t
     GROUP BY users, month
    ) q
  GROUP BY q.users  
  HAVING sum(q.cnt1) = sum(q.cnt2)
  GROUP BY q.users

  users
  -----
    2
    4

Rextester Demo

答案 2 :(得分:0)

也许您可以使用相关的子查询,例如:

jTable

答案 3 :(得分:0)

您需要将> 10的月份数与最短日期和最长日期之间的月份数进行比较:

SELECT users, Count(flag) AS months, Min(mth), Max(mth)
FROM
 (
   SELECT users, date_trunc('month',transaction_date) AS mth, 
      CASE WHEN Sum(amount) > 10 THEN 1 end AS flag
   FROM tab t
   GROUP BY users, mth
 ) AS dt
GROUP BY users  
HAVING -- adding the number of months > 10 to the min date and compare to max
   Min(mth) + (INTERVAL '1' MONTH * (Count(flag)-1)) = Max(mth)

如果缺少的月份不算在内,那将是简单的count(flag) = count(*)