【问题标题】:POSTGRESQL: How to run calculations for different datesPOSTGRESQL:如何运行不同日期的计算
【发布时间】:2017-07-14 02:56:08
【问题描述】:

我正在尝试找出每个月的活跃用户(按年龄分组)。我尝试使用子查询,但出现错误。有没有体面的方法来做到这一点?谢谢!

with first_date_of_month as
(
SELECT current_date - (interval '1 month' * s.a) AS dates FROM 
generate_series(0,24,1) AS s(a)
)


select q1.dates from first_date_of_month
where exists (select 
case when round ((CURRENT_DATE - date_of_birth)/365) =<18 then '0-18'
     ...
     when round ((CURRENT_DATE - date_of_birth)/365) >= 65 then '65+'
     Else 'N/A' end as "Age",
     count(1)
from users
and signup_date between q1.dates-INTERVAL '2 months' and q1.dates
group by 1 order by 1) ;

【问题讨论】:

  • 您的查询毫无意义。尝试显示示例数据和所需结果。

标签: postgresql date time subquery series


【解决方案1】:

首先,generate_series() 可以使用时间戳:

test=# select * from generate_series('2017-01-01', now(), interval '1 month');
    generate_series
------------------------
 2017-01-01 00:00:00+00
 2017-02-01 00:00:00+00
 2017-03-01 00:00:00+00
 2017-04-01 00:00:00+00
 2017-05-01 00:00:00+00
 2017-06-01 00:00:00+00
 2017-07-01 00:00:00+00
(7 rows)

其次,还有一个特殊的函数可以获取年龄,它居然叫age()并返回区间:

test=# select age(now(), '1981-11-18');
                   age
-----------------------------------------
 35 years 7 mons 26 days 03:07:41.561932

接下来,您可以使用extract():从间隔中提取年份:

test=# select extract(year from age(now(), '1981-11-18'));
 date_part
-----------
        35
(1 row)

最后,据我了解,您希望获取每个月按年龄分组的用户计数 - 所以这看起来您需要 2 个级别的分组。

结果,我们得到了这个(我在这里使用多个 CTE 阶段,在第二个 CTE 阶段使用隐式 CROSS JOIN,最后,我在主 CTE 查询中根据需要减少“年龄”组的数量,当组与“原始”年龄已经获得):

with dates(month) as (
  select generate_series(
    date_trunc('day', now() - interval '2 year'),
    now(), interval '1 month'
  )
), usrs_full_age as (
  select
    month,
    extract(year from age(now(), date_of_birth)) as age,
    count(*) as count
  from users u, dates
  where signup_date between month - interval '2 month' and month
  group by 1, 2
)
select
  month::date,
  case
    when age <= 18 then '0-18'
    -- ...
    else 'N/A' -- NULLs will go here (records with empty date_of_birth)
  end as age,
  sum(count) as count
from usrs_full_age
group by 1, 2
order by 1, 2
;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-15
    • 1970-01-01
    • 1970-01-01
    • 2020-05-31
    • 2017-03-25
    • 2020-08-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多