假设:
with
m as (
select 1 ID, cast('03/01/2015' as datetime) PERIOD_START, cast('3/31/2015' as datetime) PERIOD_END
union all
select 1 ID, '04/01/2015', '4/28/2015'
union all
select 1 ID, '05/01/2015', '5/31/2015'
union all
select 1 ID, '06/01/2015', '06/30/2015'
union all
select 1 ID, '07/01/2015', '07/31/2015'
)
,
a as (
SELECT 1 ID, cast('2015-03-13 14:17:00.000' as datetime) AUDIT_TIME, 'READ [2]' STATUS
UNION ALL
SELECT 1 ID, '2015-04-27 15:51:00.000' AUDIT_TIME, 'HELD [2]' STATUS
UNION ALL
SELECT 1 ID, '2015-07-08 17:54:00.000' AUDIT_TIME, 'COMPLETED [5]' STATUS
)
此查询:
select m.ID,PERIOD_START,PERIOD_END
,a.AUDIT_TIME,STATUS
from m
LEFT OUTER JOIN a on m.id=a.id
and a.audit_time between m.period_start and m.period_end
生成此记录集:
ID PERIOD_START PERIOD_END AUDIT_TIME STATUS
1 2015-03-01 00:00:00.000 2015-03-31 00:00:00.000 2015-03-13 14:17:00.000 READ [2]
1 2015-04-01 00:00:00.000 2015-04-28 00:00:00.000 2015-04-27 15:51:00.000 HELD [2]
1 2015-05-01 00:00:00.000 2015-05-31 00:00:00.000 NULL NULL
1 2015-06-01 00:00:00.000 2015-06-30 00:00:00.000 NULL NULL
1 2015-07-01 00:00:00.000 2015-07-31 00:00:00.000 2015-07-08 17:54:00.000 COMPLETED [5]
我需要在5月和6月重复4/27/15条目:
ID PERIOD_START PERIOD_END AUDIT_TIME STATUS
1 2015-03-01 00:00:00.000 2015-03-31 00:00:00.000 2015-03-13 14:17:00.000 READ [2]
1 2015-04-01 00:00:00.000 2015-04-28 00:00:00.000 2015-04-27 15:51:00.000 HELD [2]
1 2015-05-01 00:00:00.000 2015-05-31 00:00:00.000 2015-04-27 15:51:00.000 HELD [2]
1 2015-06-01 00:00:00.000 2015-06-30 00:00:00.000 2015-04-27 15:51:00.000 HELD [2]
1 2015-07-01 00:00:00.000 2015-07-31 00:00:00.000 2015-07-08 17:54:00.000 COMPLETED [5]
使用LAG()
功能:
select m.ID,PERIOD_START,PERIOD_END
,a.AUDIT_TIME
,LAG(audit_time) OVER (partition by m.ID order by period_start) PRIOR_AUDIT_TIME
,STATUS
,LAG(STATUS) OVER (partition by m.ID order by period_start) PRIOR_STATUS
from m
LEFT OUTER JOIN a on m.id=a.id
and a.audit_time between m.period_start and m.period_end
仅适用于单行:
ID PERIOD_START PERIOD_END AUDIT_TIME PRIOR_AUDIT_TIME STATUS PRIOR_STATUS
1 2015-03-01 00:00:00.000 2015-03-31 00:00:00.000 2015-03-13 14:17:00.000 NULL READ [2] NULL
1 2015-04-01 00:00:00.000 2015-04-28 00:00:00.000 2015-04-27 15:51:00.000 2015-03-13 14:17:00.000 HELD [2] READ [2]
1 2015-05-01 00:00:00.000 2015-05-31 00:00:00.000 NULL 2015-04-27 15:51:00.000 NULL HELD [2]
1 2015-06-01 00:00:00.000 2015-06-30 00:00:00.000 NULL NULL NULL NULL
1 2015-07-01 00:00:00.000 2015-07-31 00:00:00.000 2015-07-08 17:54:00.000 NULL COMPLETED [5] NULL
有没有办法在不必使用游标的情况下执行此操作?
答案 0 :(得分:0)
您可以使用窗口函数执行此操作:
with q as (
select m.ID, PERIOD_START, PERIOD_END, a.AUDIT_TIME, STATUS
from m LEFT OUTER JOIN
a
on m.id = a.id and
a.audit_time between m.period_start and m.period_end
)
select q.*,
max(status) over (partition by id, audit_grp) as imputed_status
from (select q.*,
max(audit_time) over (partition by id order by period_start) as audit_grp
from q
) q
我们的想法是使用audit_time
作为累积窗口函数来复制max()
值。然后,这定义了组,因此您也可以获得状态。
ANSI将IGNORE NULLS
指令提供给LAG()
,但SQL Server(尚未)支持它。