数据库my_table
:
id seq start_date end_date
1 1 01-01-2017 02-01-2017
1 2 07-01-2017 09-01-2017
1 3 11-01-2017 11-01-2017
2 1 20-01-2017 20-01-2017
3 1 01-02-2017 02-02-2017
3 2 03-02-2017 04-02-2017
3 3 08-01-2017 09-02-2017
3 4 09-01-2017 10-02-2017
3 5 10-01-2017 12-02-2017
我的要求是获取第一个日期(通常为seq 1开始日期)和结束日期(通常是最后一个seq结束日期)以及每个唯一ID的所有seq期间发生的日期数。
发生日期:
id 1 2 3
01-01-2017 20-01-2017 01-02-2017
02-01-2017 02-02-2017
07-01-2017 03-02-2017
08-01-2017 04-02-2017
09-01-2017 08-02-2017
11-01-2017 09-02-2017
10-02-2017
11-02-2017
12-02-2017
total 6 1 9
这是我想要的结果:
id start_date end_date num_date
1 01-01-2017 11-01-2017 6
2 20-01-2017 20-01-2017 1
3 01-02-2017 12-02-2017 9
我试过了
SELECT id
, MIN(start_date)
, MAX(end_date)
, SUM(end_date - start_date + 1)
FROM my_table
GROUP BY id
并且此SQL语句在id 1和2中正常工作,因为开始日期和结束日期之间没有重叠日期。但是对于id 3,结果num_date
是11.你能否建议使用SQL语句来解决这个问题?谢谢。
还有一个问题:数据库中的日期是datetime
格式。如何将其转换为date
。我尝试使用TRUNC
函数,但它有时会将日期转换为昨天。
答案 0 :(得分:1)
您需要计算end_date
等于以下start_date
的次数。为此,您需要使用lag()
或lead()
分析函数。您可以使用case
表达式进行比较,但是您无法将案例表达式包装在同一查询中的COUNT
或SUM
内;你需要一个子查询和一个外部查询。
像这样的东西;未经测试,因为您没有提供CREATE TABLE和INSERT语句来重新创建示例数据。
select id, min(start_date) as start_date, max(end_date) as end_date,
sum(end_date - start_date + 1 - flag) as num_days
from ( select id, start_date, end_date,
case when start_date = lag(end_date)
over (partition by id order by end_date) then 1
else 0 end as flag
from my_table
)
group by id;
答案 1 :(得分:0)
SELECT id,
MIN( start_date ) AS start_date,
MAX( end_date ) AS end_date,
SUM( end_date - start_date + 1 ) AS num_days
FROM (
SELECT id,
GREATEST(
start_date,
COALESCE(
LAG( end_date ) OVER ( PARTITION BY id ORDER BY seq ) + 1,
start_date
)
) AS start_date,
end_date
FROM your_table
)
WHERE start_date <= end_date
GROUP BY id;