【发布时间】:2017-02-23 09:45:02
【问题描述】:
我正在尝试计算许多日期范围的全局持续时间。
在我的数据库中,我有候选人和经验。
一个候选人可能有很多经验,一个经验有一个开始日期,也可能有一个结束日期。
体验日期范围可以重叠,我卡在这里,如何计算持续时间?
这就是我加入模型的方式:
我想通过查询经验和技能来检索候选人列表: 我有 2 个输入,范围和技能名称。例如,我希望所有候选人都通过经验和经验技能拥有“Ruby”技能,并且经验全球持续时间为 5 年。
编辑
目前的解决方案:
SELECT * FROM (
WITH cte AS (
SELECT
experiences.candidate_id AS candidate_id,
experiences.id AS e_id,
experiences.start_at AS start_at,
experiences.end_at AS end_at,
LAG(experiences.start_at, 1, start_at)
OVER (PARTITION BY experiences.candidate_id ORDER BY experiences.start_at) AS prev_start_at,
LAG(experiences.end_at, 1, start_at)
OVER (PARTITION BY experiences.candidate_id ORDER BY experiences.start_at) AS prev_end_at,
LEAD(experiences.start_at)
OVER (PARTITION BY experiences.candidate_id ORDER BY experiences.start_at) AS next_start_at,
LEAD(experiences.end_at, 1, current_date)
OVER (PARTITION BY experiences.candidate_id ORDER BY experiences.start_at) AS next_end_at
FROM experiences
INNER JOIN experiences_skills ON experiences_skills.experience_id = experiences.id
INNER JOIN skills ON skills.id = experiences_skills.skill_id
WHERE skills.name = 'Ruby'
)
SELECT
SUM(CASE
WHEN (cte.prev_end_at > cte.end_at AND cte.prev_end_at < cte.next_start_at)
THEN cte.prev_end_at
WHEN (cte.prev_end_at > cte.end_at AND cte.prev_end_at > cte.next_start_at)
THEN cte.next_start_at
WHEN cte.end_at > cte.next_start_at
THEN cte.next_start_at
ELSE cte.end_at
END
-
cte.start_at
) AS duration_day,
candidates.*
FROM cte
INNER JOIN candidates ON candidates.id = cte.candidate_id
GROUP BY candidates.id
) AS candidates
WHERE duration_day > 0 AND duration_day < 1000';
【问题讨论】:
-
样本数据和期望的结果会有所帮助
-
好的,我会在 5 分钟内添加这个
-
所以,如果我做对了,候选人可以在同一技能上拥有多个经验,这些经验可能(或可能不)重叠并且您想要这些经验长度的总和(没有重叠部分)? -- 因此,在您的示例中,如果候选人有 2 种 Ruby 技能的经验:f.ex。
2010-2013和2011-2014并且您查询 5 年 的全球持续时间,则该候选人不符合条件,因为(没有重叠)他/她在 2010 年至 2014 年期间拥有该技能的经验(只有 4 年)? -
另外,如果体验没有
end_at,我假设你会用current_timestamp计算(或者current_date也许?end_at的确切类型是什么?)。开放范围没有多大意义,因为它的长度是无限的(它总是大于查询的有限全局持续时间)。 -
没错,让我发布我目前的解决方案。查看我的编辑
标签: sql ruby-on-rails database postgresql