我认为这是一个常见的数据仓库问题。
我一直在尝试做的是在日期之间没有间隙的SQL查询。
事实表仅记录测量并记录到表中的记录。本案涉及海上船舶的注册石油生产。有些日子,某些船上没有制作。
所以这是我的简单数据仓库:DimVessel
,DimDate
和FactProduction
。在下面你看到我想要的最终结果集。
我希望SQL查询用vesselkey
和Production
填充事实表,即使容器上没有生产。请记住,有些日子可以在几艘船上生产,其他日子可以生产所有船只(最好的情况)。
我希望有人可以帮助我。
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
答案 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
如果结果不是你要找的那个,请告诉我。