这是我的先决条件。
user_id | module_start_date | module_end_date | loading
6 | 01-01-2013 | 31-01-2013 | 0.4
6 | 16-01-2013 | 31-01-2013 | 0.2
6 | 01-03-2013 | 15-03-2013 | 0.7
6 | 30-01-2013 | 30-01-2013 | 0.5
我必须添加加载并更改日期范围,如图所示。 使用相同的start_date和end_date可以在上述条件中添加面临的问题。
注意: - 可能有多个用户。
user_id | module_start_date| module_end_date | loading
6 | 01-01-2013 | 15-01-2013 | 0.4
6 | 16-01-2013 | 29-01-2013 | 0.6
6 | 30-01-2013 | 30-01-2013 | 1.1
6 | 31-01-2013 | 31-01-2013 | 0.6
6 | 01-03-2013 | 15-03-2013 | 0.7
答案 0 :(得分:0)
如果您的结束日期是独家的,这将会更容易一些。不过,这是一个计划:
暂时增加每个范围内的结束日期,使其成为独家日期。
将所有开始日期和结束日期放入一个列表中,仅提取不同的日期。
将每两个日期彼此相邻以形成新范围。
将新范围列表加入到结束日期增加的列表中,按新范围分组并获取loading
的总计。
将新范围转换为原始"全包"通过将每个结束日期减1来格式化。
这是上述计划的实施:
WITH converted AS (
-- #1
SELECT
user_id,
module_start_date,
module_end_date = DATEADD(DAY, 1, module_end_date),
loading
FROM atable
),
datesranked AS (
-- #2
SELECT
c.user_id,
x.date,
rnk = ROW_NUMBER() OVER (PARTITION BY c.user_id ORDER BY x.date)
FROM converted AS c
CROSS APPLY (
VALUES (c.module_start_date), (c.module_end_date)
) AS x (date)
GROUP BY
c.user_id,
x.date
),
newranges AS (
-- #3
SELECT
d1.user_id,
module_start_date = d1.date,
module_end_date = d2.date
FROM
datesranked AS d1
INNER JOIN datesranked AS d2
ON d1.user_id = d2.user_id
AND d1.rnk = d2.rnk - 1
),
totals AS (
-- #4 & #5
SELECT
new.user_id,
new.module_start_date,
module_end_date = DATEADD(DAY, -1, new.module_end_date),
loading = SUM(old.loading)
FROM newranges AS new
INNER JOIN converted AS old
ON new.user_id = old.user_id
AND new.module_end_date > old.module_start_date
AND new.module_start_date < old.module_end_date
GROUP BY
new.user_id,
new.module_start_date,
new.module_end_date
)
SELECT *
FROM totals
;
上面的实现是SQL Fiddle demo。