Postgres:计算过去十年的工作月数

时间:2015-03-05 04:04:31

标签: postgresql

我用户表和工作。用户有很多工作,工作有start_date和end_date:

     Column     |            Type             |                     Modifiers                     
----------------+-----------------------------+---------------------------------------------------
 id             | integer                     | not null default nextval('jobs_id_seq'::regclass)
 title          | character varying           | 
 employer       | character varying           | 
 start_date     | date                        | 
 end_date       | date                        | 
 user_id        | integer                     | 

我需要计算一个人在过去X年中工作的总月数。

我看了OVERLAPS并稍微玩了一会儿,但我无法弄清楚我需要什么。我想确保即使start_date超出X年范围,我仍然会计算范围内的月份。

这是我到目前为止所做的:

select sum(EXTRACT(YEAR FROM months) * 12 + EXTRACT(MONTH FROM months))
 as working_months
from (
select CASE current
 WHEN true THEN
 age(current_date, start_date)
 ELSE age(end_date, start_date) 
END as months
 from jobs inner join users on jobs.user_id = users.id
 where users.id = 4
) as employment_time;

2 个答案:

答案 0 :(得分:0)

基本查询是这样的:

SELECT sum(extract(year from months) * 12 + extract(month from months)) AS working_months
FROM (
  SELECT
    age(CASE (start_date, start_date) OVERLAPS (current_date, interval '-5 years')
        WHEN true THEN start_date
        ELSE current_date - interval '5 years'
        END AS strt::timestamp,
        CASE current
        WHEN true THEN current_date
        ELSE end_date
        END AS fin::timestamp) AS months
  FROM jobs
  WHERE user_id = 4) AS employment_time;

您也可以将它放在一个带有年数和user_id参数的SQL函数中。请注意,您将从个别工作中丢弃部分月份。您可以将extract(day from months) / 30添加到顶部SELECT,以将这些部分月份收入整月。

这假设作业不能重叠。如果他们这样做,那么查询会变得复杂得多。

答案 1 :(得分:0)

with jobs (start_date, end_date, user_id) as ( values
    ('2000-01-01'::date, '2005-12-31'::date, 1),
    ('2007-10-01', '2008-09-30', 1),
    ('2010-09-01', '2014-10-20', 1)
)
select
    user_id,
    extract(year from work_time) * 12 + extract(month from work_time) as months
from (
    select
        user_id,
        sum(age(upper(period), lower(period))) as work_time
    from (
        select
            user_id,
            daterange(start_date, end_date, '[]') *
            daterange((current_date - interval '10 years')::date, current_date)
            as period
        from jobs
    ) s
    group by user_id
) s
;
 user_id | months 
---------+--------
       1 |     70

Range type - Range functions