SQL填写缺少日期

时间:2016-05-30 16:20:45

标签: sql sql-server

我认为这是一个常见的数据仓库问题。

我一直在尝试做的是在日期之间没有间隙的SQL查询。

事实表仅记录测量并记录到表中的记录。本案涉及海上船舶的注册石油生产。有些日子,某些船上没有制作。

所以这是我的简单数据仓库:DimVesselDimDateFactProduction。在下面你看到我想要的最终结果集。

我希望SQL查询用vesselkeyProduction填充事实表,即使容器上没有生产。请记住,有些日子可以在几艘船上生产,其他日子可以生产所有船只(最好的情况)。

我希望有人可以帮助我。

DimVessel

VesselKey| VesselName
1        | Vessel 1
2        | Vessel 2
3        | Vessel 3
4        | Vessel 4
5        | Vessel 5

DimDate

DateKey     |Date
20160517    |2016-05-17 00:00:00.000
20160518    |2016-05-18 00:00:00.000
20160519    |2016-05-19 00:00:00.000
20160520    |2016-05-20 00:00:00.000

FactProduction

DateKey     |VesselKey  |Production
20160517    |4          |12505
20160517    |5          |1276
20160517    |3          |88
20160517    |2          |3919
20160518    |4          |8785
20160518    |5          |736
20160518    |1          |3754
20160518    |2          |5654
20160519    |2          |1654
20160520    |1          |2016
20160520    |3          |6059
20160520    |4          |10980
20160520    |5          |663

这就是我想要的,最终结果集:

DateKey     |VesselKey  |Production
20160517    |4          |12505
20160517    |5          |1276
20160517    |3          |88
20160517    |2          |3919
20160517    |1          |0
20160518    |4          |8785
20160518    |5          |736
20160518    |3          |0
20160518    |1          |3754
20160518    |2          |5654
20160519    |2          |1654
20160519    |1          |0
20160519    |3          |0
20160519    |4          |0
20160519    |5          |0
20160520    |1          |2016
20160520    |3          |6059
20160520    |2          |4059
20160520    |4          |10980
20160520    |5          |663

2 个答案:

答案 0 :(得分:0)

为什么要存储不存在的数据?我不喜欢存储源系统中实际不存在的事实数据。

您可以使用下面的查询(未测试)

获得所需的结果
SELECT DD.DateKey
,DV.VesselKey
,Production = ISNULL(FP.Production)
FROM DimDate DD
    INNER JOIN DimVessel DV ON 1 = 1
    LEFT JOIN FactProduction FP ON (FP.DateKey = DD.DateKey AND FP.VesselKey = DV.VesselKey)
WHERE DD.DateKey BETWEEN @StartDate AND @EndDate

如果您坚持想要存储数据,那么您只需要在源数据中添加连接而不是FactProduction表,然后将结果插入到您的事实中

答案 1 :(得分:0)

这是一个有效的解决方案:

select  allCombinations.DateKey,
        allCombinations.VesselKey,
        isnull(p.Production, 0) as Production
from    (
         select d.DateKey,
                v.VesselKey
         from   @Dates as d
         cross join @Vessels as v
        ) as allCombinations
left join @Production as p
on      allCombinations.DateKey = p.DateKey
        and allCombinations.VesselKey = p.VesselKey

验证此解决方案的完整代码如下:

declare @Vessels table
    (
     VesselKey int primary key
                   not null,
     VesselName as (N'Vessel ' + cast(VesselKey as nvarchar))
    )

insert  into @Vessels
        (VesselKey)
values  (1),
        (2),
        (3),
        (4),
        (5)

select  *
from    @Vessels as v

declare @Dates table
    (
     DateKey int primary key
                 not null,
     Date as (try_convert(datetime2, cast(DateKey as nvarchar)
              + ' 00:00:00.000'))
    )

insert  into @Dates
        (DateKey)
values  (20160517),
        (20160518),
        (20160519),
        (20160520)

select  *
from    @Dates as d

declare @Production table
    (
     DateKey int,
     VesselKey int,
     Production int
    )

insert  into @Production
        (DateKey, VesselKey, Production)
values  (20160517, 4, 12505),
        (20160517, 5, 1276),
        (20160517, 3, 88),
        (20160517, 2, 3919),
        (20160518, 4, 8785),
        (20160518, 5, 736),
        (20160518, 1, 3754),
        (20160518, 2, 5654),
        (20160519, 2, 1654),
        (20160520, 1, 2016),
        (20160520, 3, 6059),
        (20160520, 4, 10980),
        (20160520, 5, 663)

select  *
from    @Production as p



select  allCombinations.DateKey,
        allCombinations.VesselKey,
        isnull(p.Production, 0) as Production
from    (
         select d.DateKey,
                v.VesselKey
         from   @Dates as d
         cross join @Vessels as v
        ) as allCombinations
left join @Production as p
on      allCombinations.DateKey = p.DateKey
        and allCombinations.VesselKey = p.VesselKey

如果结果不是你要找的那个,请告诉我。