如何使用Postgresql在一个报告中生成每月群组?

时间:2016-10-06 18:43:49

标签: sql postgresql

原始表User

ID   Created_Date   SubmittedAt   ApprovedAt

原始表Campaign

User_ID   Clicked_At

现在我想生成一个包含

等列的报告
Month  Year  #Applicants  #Submitted  #Approved

我使用postgresql编写了查询:

SELECT To_char(C.clicked_at, 'MON')    AS MON, 
       Extract(year FROM C.clicked_at) AS YYYY, 
       CASE 
         WHEN created_date IS NOT NULL THEN Count(user_id) 
       END AS APPLICANTS, 
       CASE 
         WHEN submittedat IS NOT NULL THEN Count(user_id) 
       END AS SUBMITTED, 
       CASE 
         WHEN approvedat IS NOT NULL THEN Count(user_id) 
       END AS APPROVED 
FROM   campaign C, 
       users U 
WHERE  C.user_id = U.id 
GROUP  BY 1,2 

我收到一条错误消息“u.created_date必须出现在GROUP BY子句中,或者在聚合函数中使用。但是,我只希望我的结果按year分组{ {1}}。

2 个答案:

答案 0 :(得分:1)

首先,使用正确的,明确的JOIN语法。其次,如果要计算非空值的数量,则可以简化代码:

SELECT TO_CHAR(C.CLICKED_AT, 'MON') AS MON,
       EXTRACT(YEAR FROM C.CLICKED_AT) AS YYYY,
       COUNT(CREATED_DATE) AS APPLICANTS,
       COUNT(SUBMITTEDATE) AS SUBMITTED,
       COUNT(APPROVEDAT) AS APPROVED
FROM CAMPAIGN C JOIN
     USERS U
     ON C.USER_ID = U.ID
GROUP BY 1, 2;

通过这种简化,您根本不再拥有任何(显式)条件逻辑,因此group by子句没问题。

我建议您将月份和年份结合起来并对结果进行排序:

SELECT TO_CHAR(C.CLICKED_AT, 'YYYY-MM') AS yyyymm,
       COUNT(CREATED_DATE) AS APPLICANTS,
       COUNT(SUBMITTEDATE) AS SUBMITTED,
       COUNT(APPROVEDAT) AS APPROVED
FROM CAMPAIGN C JOIN
     USERS U
     ON C.USER_ID = U.ID
GROUP BY 1
ORDER BY 1;

答案 1 :(得分:0)

您需要将CASE语句放在聚合函数中:

SELECT TO_CHAR(C.CLICKED_AT,'MON') AS MON,
EXTRACT(YEAR FROM C.CLICKED_AT) AS YYYY,
COUNT(CASE WHEN CREATED_DATE IS NOT NULL THEN USER_ID END) AS APPLICANTS,
COUNT(CASE WHEN SUBMITTEDAT IS NOT NULL THEN USER_ID END) AS SUBMITTED,
COUNT(CASE WHEN APPROVEDAT IS NOT NULL THEN USER_ID END) AS APPROVED
FROM
CAMPAIGN C
JOIN USERS U ON C.USER_ID = U.ID
GROUP BY 1,2

注意:

  • 如果您使用的是Postgres 9.4+,那么您可以使用FILTER子句。
  • 使用显式JOIN子句代替WHERE子句来连接表
  • 您可能会更好地扩展您的TO_CHAR()以接受年月

示例:

SELECT TO_CHAR(C.CLICKED_AT,'YYYY-MM') AS date_year_month,
COUNT(CASE WHEN CREATED_DATE IS NOT NULL THEN USER_ID END) AS APPLICANTS,
COUNT(CASE WHEN SUBMITTEDAT IS NOT NULL THEN USER_ID END) AS SUBMITTED,
COUNT(CASE WHEN APPROVEDAT IS NOT NULL THEN USER_ID END) AS APPROVED
FROM
CAMPAIGN C
JOIN USERS U ON C.USER_ID = U.ID
GROUP BY 1