使用开始日期和结束日期,我们需要选择每天的列值,或使用最近日期存在数据的值。
例如,使用此示例数据
create table #t1
(location char(2),
item varchar(6),
postdate date,
posttime time,
qoh int)
insert #t1 select 'FL', 'itemA', '1/1/2014', '0900', 10
insert #t1 select 'FL', 'itemA', '1/1/2014', '0100', 11
insert #t1 select 'NY', 'itemA', '1/1/2014', '1100', 50
insert #t1 select 'NY', 'itemA', '1/1/2014', '0900', 51;
insert #t1 select 'FL', 'itemB', '1/1/2014', '0900', 100
insert #t1 select 'FL', 'itemB', '1/1/2014', '0100', 101
insert #t1 select 'NY', 'itemB', '1/1/2014', '1100', 150
insert #t1 select 'NY', 'itemB', '1/1/2014', '0900', 151;
insert #t1 select 'FL', 'itemA', '1/5/2014', '0900', 510
insert #t1 select 'FL', 'itemA', '1/5/2014', '0100', 511
insert #t1 select 'NY', 'itemA', '1/5/2014', '1100', 550
insert #t1 select 'NY', 'itemA', '1/5/2014', '0900', 551;
insert #t1 select 'FL', 'itemB', '1/5/2014', '0900', 5100
insert #t1 select 'FL', 'itemB', '1/5/2014', '0100', 5101
insert #t1 select 'NY', 'itemB', '1/5/2014', '1100', 5150
insert #t1 select 'NY', 'itemB', '1/5/2014', '0900', 5151;
我想为1/1和1/6之间的所有日期选择每个位置,项目和最后余额。对于没有条目的日期,例如1/2,没有任何记录,所以我想使用上一个已知日期1/1的值,并对所有其他日期使用这个类似的逻辑。
我想要的结果是
date Location Item OHB2
2014-01-01 FL itemA 11
2014-01-01 FL itemB 101
2014-01-01 NY itemA 51
2014-01-01 NY itemB 151
2014-01-02 FL itemA 11
2014-01-02 FL itemB 101
2014-01-02 NY itemA 51
2014-01-02 NY itemB 151
2014-01-03 FL itemA 11
2014-01-03 FL itemB 101
2014-01-03 NY itemA 51
2014-01-03 NY itemB 151
2014-01-04 FL itemA 11
2014-01-04 FL itemB 101
2014-01-04 NY itemA 51
2014-01-04 NY itemB 151
2014-01-05 FL itemA 510
2014-01-05 FL itemB 5100
2014-01-05 NY itemA 550
2014-01-05 NY itemB 5150
2014-01-06 FL itemA 510
2014-01-06 FL itemB 5100
2014-01-06 NY itemA 550
2014-01-06 NY itemB 5150
到目前为止,这是我尝试过的,直到我开始使用更大的日期范围。然后它开始在我的实际数据库中非常缓慢地运行,其中涉及100万行。当SELECT TOP部分被注释掉时,它运行得非常快。
WITH dates AS
(
SELECT CAST('1/1/2014' AS DATE) 'date',
1 AS RN
UNION ALL
SELECT DATEADD(day, 1, D.date),
1 AS RN
FROM dates D
WHERE DATEADD(dd, 1, D.date) <= '1/6/2014'
)
SELECT dates.[date],
I.Location,
I.Item,
(SELECT TOP 1 #t1.qoh FROM #t1
WHERE #t1.location = I.Location
AND #t1.item = I.Item
AND #t1.postdate <= dates.[date]
ORDER BY #t1.postdate DESC, #t1.posttime DESC) AS OHB2
FROM dates
INNER JOIN
(
SELECT 1 AS RN2,
#t1.location AS Location,
#t1.item AS Item
FROM #t1
GROUP BY #t1.location,
#t1.item) I
ON dates.RN = I.RN2
ORDER BY dates.[date] ASC, I.Location ASC, I.Item ASC
OPTION (MAXRECURSION 32767)
答案 0 :(得分:0)
使用您的日期CTE。
;WITH dates AS
(
SELECT CAST('1/1/2014' AS DATE) 'date',
1 AS RN
UNION ALL
SELECT DATEADD(day, 1, D.date),
1 AS RN
FROM dates D
WHERE DATEADD(dd, 1, D.date) <= '1/6/2014'
)
SELECT d.[date], I.location, I.item, i.qoh
FROM dates d
CROSS JOIN (SELECT DISTINCT location, item
FROM #t1) a
CROSS APPLY (SELECT TOP 1 *
FROM #t1 t
WHERE t.postdate <= d.date
AND a.location = t.location
AND a.item = t.item
ORDER BY t.postdate
DESC) i
ORDER BY i.postdate