【问题标题】:Generate a result set for every day using values for current day or values from most recent day使用当天的值或最近一天的值生成每天的结果集
【发布时间】: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)

【问题讨论】:

    标签: sql tsql


    【解决方案1】:

    使用您的日期 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
    

    【讨论】:

    • 这太棒了 Ennui!它是交叉连接和交叉应用的完美应用。切换到此方法后,我的查询时间缩短了一半。
    猜你喜欢
    • 2021-07-12
    • 2016-06-15
    • 1970-01-01
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    相关资源
    最近更新 更多