【发布时间】:2014-03-21 00:07:17
【问题描述】:
使用开始日期和结束日期,我们需要选择每一天的列值或使用数据存在的最近日期的值。
例如,使用这个样本数据
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)
【问题讨论】: