Postgresql 研究生:计算过去X年的工作月数
我有一个用户表和一个作业。用户有许多作业,作业有开始日期和结束日期:Postgresql 研究生:计算过去X年的工作月数,postgresql,Postgresql,我有一个用户表和一个作业。用户有许多作业,作业有开始日期和结束日期: Column | Type | Modifiers ----------------+-----------------------------+--------------------------------------------------- id |
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年内工作的总月数
我已经看了一些重叠和间歇,但我不太清楚我需要什么。我想确保即使开始日期在X年范围之外,我仍然计算在该范围内的月份
以下是我到目前为止的情况:
选择sumEXTRACTYEAR FROM months*12+EXTRACTMONTH FROM months
作为工作月
从…起
选择当前案例
那么什么时候是真的
年龄当前日期,开始日期
其他日期结束日期、开始日期
以月份结束
从作业内部加入作业上的用户。用户\u id=users.id
其中users.id=4
随着时间的推移;
基本查询如下:
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;
您也可以将其放入一个SQL函数中,该函数的参数为年数和用户id。请注意,您会从单个作业中丢弃部分月份。您可以将extractday from months/30添加到顶部选择,以将部分月份收获为完整月份
这假设作业不能重叠。如果他们这样做了,那么查询就会变得更加复杂
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
-
出于某种原因,Postgres对间隔'-X years'中的括号不满意,但当我删除它们时,它会在末尾吐出start::timestamp。@MikeWilliamson:我的错。Start是SQL保留字,间隔不需要括号。答案已更新。