SQL Server SQL"向下填充"源表中不存在的数据

时间:2014-05-28 18:36:46

标签: sql sql-server

我们说我有一张桌子,里面有日期。然后我有一个具有一些维度和一个事实列的表。其中一个维度也是日期,但日期比第一个表少。第一张表每个月的第1个月都有20年,前进20年。

我想加入2个表,其中最终结果是表示日期表中的每个日期并使用第2个表中的数据填充。当事实表中的2个给定日期之间没有数据时,我想用最后的已知数据填充它。

因此,日期表的表格结构只有1列,这是一个日期,并且每月1日填写40年。

第二个表定义为:company(varchar),type(varchar),dt(datetime),value(float)

让我们说我在第二张表中有值,如:

'Company A', 'Retail', '5/1/2014', 3.5
'Company A', 'Retail', '7/1/2014', 4

注意此表中没有6/1/2014记录,但此日期记录存在于日期表中。因此,当我完成查询后,结果应如下所示:

'Company A', 'Retail', '5/1/2014', 3.5
'Company A', 'Retail', '6/1/2014', 3.5
'Company A', 'Retail', '7/1/2014', 4

注意3.5和所有其他字段(日期除外)如何向下移入缺失日期记录。你可以说,这个顺序变得非常重要。

我不确定这是否可以通过查询来完成,但结果需要传递给需要查询/表而不是存储过程的事物,并且需要某种过程来更新像这样的表格确实运作良好,因为这些数据的输入是通过一个网站完成的,该网站有很多用户,结果应该是即时的。

希望这是有道理的,任何帮助我们的想法都会受到高度赞赏。

2 个答案:

答案 0 :(得分:2)

假设您的事实表只有每月第一天的信息,那么这应该适合您。如果您的事实表有其他信息,那么您很可能会获取该数据。即如果您有5月30日的数据,该信息将插入6月1日的日期。

SELECT t2.company, t2.type, t1.dt, t2.value
FROM tbldata t1,
      tblfact t2
WHERE t2.dt <= t1.dt
AND   NOT EXISTS (SELECT top 1 1
                  FROM tblfact t22
                  WHERE t22.dt <= t1.dt
                  AND   t22.dt > t2.dt)

SQL Fiddle

答案 1 :(得分:1)

这是我不太好的例子:

DECLARE @Dates TABLE (dates datetime)

INSERT INTO @Dates SELECT '5/1/2014'
INSERT INTO @Dates SELECT '6/1/2014'
INSERT INTO @Dates SELECT '7/1/2014'
INSERT INTO @Dates SELECT '8/1/2014'
INSERT INTO @Dates SELECT '9/1/2014'
INSERT INTO @Dates SELECT '10/1/2014'
INSERT INTO @Dates SELECT '11/1/2014'

DECLARE @data TABLE ( company varchar(100), type varchar(100), dt datetime, value float)

INSERT INTO @data SELECT 'Company A', 'Retail', '5/1/2014', 3.5
INSERT INTO @data SELECT 'Company A', 'Retail', '7/1/2014', 4
INSERT INTO @data SELECT 'Company A', 'Retail', '8/1/2014', 55

;WITH a AS (
    SELECT ROW_NUMBER() OVER (ORDER BY D.dates) as RowID, dates as dt, company, type, value
    FROM @Dates AS D
    LEFT JOIN @data AS dt
        ON D.dates = dt.dt
), b AS (
    SELECT RowID, company, type, dt, value
    FROM a
    WHERE RowID = 1
    UNION ALL
    SELECT 
        a.RowID, 
        CASE WHEN a.company IS NULL THEN  b.company ELSE a.company ENd,
        CASE WHEN a.company IS NULL THEN  b.type ELSE a.type ENd,
        a.dt,
        CASE WHEN a.company IS NULL THEN  b.value ELSE a.value ENd
    FROM b
    INNER JOIN a
        ON a.RowID = b.RowID+1 

)
SELECT company, type, dt, value
FROM b