postgreSQL-计算上个月开始日期和结束日期之间的值

时间:2017-06-13 17:03:47

标签: sql postgresql

我有一张表如下

user_id   date         month  year   visiting_id
 123      11-04-2017   APRIL  2017   4500
 123      12-05-2017   MAY    2017   4567
 123      13-05-2017   MAY    2017   4568
 123      17-05-2017   MAY    2017   4569
 123      22-05-2017   MAY    2017   4570
 123      11-06-2017   JUNE   2017   4571
 123      12-06-2017   JUNE   2017   4572

我想按月计算当月和上个月的访问次数,如下所示:

user_id   month   year   visit_count_this_month  visit_count_last_month
 123      APRIL   2017               1                      0
 123      MAY     2017               4                      1
 123      JUNE    2017               2                      4

我能够使用以下查询计算visit_count_this_month

SELECT v.user_id, v.month, v.year, 
       SUM(is_visit_this_month) as visit_count_this_month
FROM
   (SELECT user_id, date, month, year,
        CASE WHEN  TO_CHAR(date, 'MM/YYYY') = TO_CHAR(date, 'MM/YYYY') 
        THEN 1 ELSE 0 
        END as is_visit_this_month
   FROM visits
   GROUP BY user_id, date, month, year
   HAVING user_id = 123) v 
GROUP BY v.user_id, v.month, v.year

但是,我一直在计算visit_count_last_month。与此类似,我也想计算visit_count_last_2months。

有人可以帮忙吗?

2 个答案:

答案 0 :(得分:1)

假设每个月都有值,您可以先获得每月的计数,然后使用lag获取每个用户上个月的值。

SELECT T.*
,COALESCE(LAG(visits,1) OVER(PARTITION BY USER_ID ORDER BY year,mth),0) as last_month_visits
,COALESCE(LAG(visits,2) OVER(PARTITION BY USER_ID ORDER BY year,mth),0) as last_2_month_visits
FROM (
SELECT user_id, extract(month from date) as mth, year, COUNT(*) as visits
FROM visits
GROUP BY user_id, extract(month from date), year
) T

如果可能缺少月份,最好在指定的时间范围内生成所有月份,并在表格left join上生成。 (这个例子显示了2017年的所有月份。)

select user_id,yr,mth,visits
,coalesce(lag(visits,1) over(PARTITION BY USER_ID ORDER BY yr,mth),0) as last_month_visits
,coalesce(lag(visits,2) OVER(PARTITION BY USER_ID ORDER BY yr,mth),0) as last_2_month_visits
from (select u.user_id,extract(year from d.dt) as yr, extract(month from d.dt) as mth,count(v.visiting_id) as visits
      from generate_series(date '2017-01-01', date '2017-12-31',interval '1 month') d(dt)
      cross join (select distinct user_id from visits) u
      left join visits v on extract(month from v.dt)=extract(month from d.dt) and extract(year from v.dt)=extract(year from d.dt) and u.user_id=v.user_id
      group by u.user_id,extract(year from d.dt), extract(month from d.dt)
      ) t

答案 1 :(得分:1)

你可以像这样使用LATERAL JOIN:

SELECT user_id, month, year, COUNT(*) as visit_count_this_month, visit_count_last_month
FROM visits v
    CROSS JOIN LATERAL (
        SELECT COUNT(*) as visit_count_last_month
        FROM visits
        WHERE user_id = v.user_id
            AND date = (CAST(v.date AS date) - interval '1 month')
  ) l
GROUP BY user_id, month, year, visit_count_last_month;

SQLFiddle - http://sqlfiddle.com/#!15/393c8/2