SQL。如何使用日期扩展表?

时间:2010-11-07 13:55:58

标签: tsql sql-server-2008

我使用的是SQL 2008。

我有一个逻辑实体(表)说数据带属性(列)(键,日期,a,b,c,d)。

问题是a和b每天都会改变值,c和d会随机改变值并且非常慢。而且它们也会针对每个键单独更改。比如c = d,key = 1将在今天和下个月改变,密钥= 2明天和一周后。

所以我的想法是拆分2. MainData(键,日期,a,b)和TemporalData(键,changeDate,c,d)

但是我没有写出有效的查询 - 如何使用它。

我在考虑某种“参数化”视图(不确定它是否可行)。假设从vwData中选择*,其中date ='xxxxx',它将返回给我一个特定日期的b,以及c,d,它们对特定的密钥和该日期有效。

我需要一种简单明了的方法来从这个构造中选择数据。我还需要它有效率,因为数据在一年内会很大

(注意:只会选择date = @singleDate之间的日期之间)

示例:

MainData             TemporalData
1 20101001 1.0 2.0   1 20101001 2.0 3.0
1 20101002 2.0 3.0   1 20101003 8.0 9.0
1 20101003 4.0 5.0   
1 20101004 6.0 3.0   

 select * from vwData where date = '20101002'

 1 20101002 2.0 3.0 2.0 3.0

 select * from vwData where date = '20101003'

 1 20101003 4.0 5.0 8.0 9.0

 select * from vwData where date = '20101004'

 1 20101004 6.0 3.0 8.0 9.0

1 个答案:

答案 0 :(得分:1)

首先,将数据拆分为一个表中更多静态数据的1:1关系,以及另一个表中经常更改的数据并不是一个糟糕的方法。其次,不清楚TemporalData.ChangeDate是否应与MainDate匹配。[Date]。假设是这种情况,那么你可以这样做:

Select MainData.Key, MainData.[Date], MainData.a, MainData.b
    , TemporalData.c, TemporalData.d
From MainData
    Left Join TemporalData
        On TemporalData.Key = MainData.Key
            And TemporalData.ChangeDate = MainDate.[Date]
Where MainData.[Date] = @SomeDate

这假设您将始终具有MainData值,但可能没有TemporalData值。您可以将其放在视图中,但无法指定参数。视图是一个虚拟表,因此表示一组无序行。因此,您的视图将如下所示:

Create View vwMain 
As
Select MainData.Key, MainData.[Date], MainData.a, MainData.b
    , TemporalData.c, TemporalData.d
From MainData
    Left Join TemporalData
        On TemporalData.Key = MainData.Key
            And TemporalData.ChangeDate = MainDate.[Date]

然后你会像这样使用视图:

Select ...
From vwMain
Where [Date] = @SomeDate

修改

看起来你想要的是总是有一个表示最近日期的TemporalData行。虽然我们可以从您的评论和示例输出中推断出这一点,但您的描述并不清楚。所以,鉴于此,这是一个解决方案。显然,最终结果不包括示例源数据的公用表表达式:

With MainData As
    (
    Select 1 As [Key], '20101001' As [Date], 1.0 As A, 2.0 As B
    Union All Select 1 As [Key], '20101002', 2.0, 3.0
    Union All Select 1 As [Key], '20101003', 4.0, 5.0
    Union All Select 1 As [Key], '20101004', 6.0, 3.0
    )
    , TemporalData As
    (
    Select 1 As [Key], '20101001' As [ChangeDate], 2.0 As C, 3.0 As D
    Union All Select 1 As [Key], '20101003', 8.0, 9.0
    )
    , RankedResults As
    (
    Select MainData.[Key], MainData.[Date], MainData.a, MainData.b
        , TemporalData.c, TemporalData.d, TemporalData.ChangeDate
        , Row_Number() Over ( Partition By MainData.[Key], MainData.[Date]
                          Order By TemporalData.ChangeDate Desc ) As Num
    From MainData
        Join TemporalData
            On TemporalData.Key = MainData.Key
               And TemporalData.ChangeDate <= MainData.[Date]
    )
Select *
From RankedResults
Where Num = 1
Order By [Date]