4

我对如何在 SQL Server 2008 R2 中得出结论有疑问。

我有一个有一些输入的表,这个输入有一个父标签和一个时间戳。

有时这些对象的父标签会在时间戳中更改。此父标签可能会不时更改。假设我有下表。我当前的表有数百万具有不同 ObjectID 的数据。看表,很容易看出 ParentID 在时间戳 3 到 4、6 到 7 和 8 到 9 中发生了变化。

ProductID      ParentID       DateID          value
--------       ---------      -------         ------------- 
  100            1              1                325,2
  100            1              2                326,2
  100            1              3                329,6
  100            2              4                335,2
  100            2              5                336,5
  100            2              6                338,3
  100            3              7                339,2
  100            3              8                342,1
  100            1              9                343,7
  100            1              10               355,6
  100            1              11               385,8

我想要的答案是 ObjectID 属于哪个 ParentID 以及开始和结束时间戳以及时间戳之间的增量值(时间戳 = TS)

ProductID      ParentID       DateID_Start   DateID_End   DeltaValue
  --------      ---------     ----------     --------     ---------- 
  100           1             1              4            10,0
  100           2             4              7            4,0
  100           3             7              9            4,5
  100           1             9              11           42,1

到目前为止,我已经完成的是当有变化时得到的,但它只给了我变化,而不是上面的表格。

ObjectID      ParentID_Old   ParentID_New    DateID_Changed   
  --------      ------------   ------------  ------------
  100           1              2              3 to 4
  100           2              3              6 to 7
  100           3              1              8 to 9

这是生成表和测试插入的代码。下面也是选择以获取更改。

        --Initial Insert Code
   IF OBJECT_ID('tempdb..#Trackings') Is Not Null
    Drop table #Trackings

 Create Table #Trackings
 (
   ProductID bigint
 , value    float
 , StoreID  int
 , DateID int
 , Aux_Row_Number int
 )

Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,1,325.2,1)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,2,326.2,2)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,3,329.6,3)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,4,335.2,4)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,5,336.5,5)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,6,338.3,6)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,7,339.2,7)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,8,342.1,8)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,9,343.7,9)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,10,355.0,10)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,12,385.0,12)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,13,485.0,13)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,14,985.0,14)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,15,1585.0,15)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,16,3585.0,16)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,17,5585.0,17)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,18,6585.0,18)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,19,8585.0,19)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,20,9585.0,20)

以及用于获取我正在使用的更改的 SQL:

Select      ISNULL(A.StoreID,-1)
,           ISNULL(B.StoreID,-1)
,           A.ProductID
,           A.value
,           B.value
,           A.DateID
,           B.DateID
From        #Trackings A
Join        #Trackings B
On          A.ProductID = B.ProductID
And         A.Aux_Row_Number + 1 = B.Aux_Row_Number
And         ISNULL(A.StoreID,-1) <> ISNULL(B.StoreID,-1)

任何灯的想法伙计们?

提前致谢!

编辑:再多一点“业务”信息:ParentID 就像一个产品的商店,而 DateID 是它到达那里的时间。所以让我们假设productID 100在ParentID 1中,这意味着在DateID 1中productID 100在Store 1中输入。所以由于某种原因它移动到DatedID 4中的Store 2。所以我在答案表中的第一行意味着ProductID 100 在 StoreID 1 中从 DateID 1 到 DateID 4。productID 100 然后在 StoredID 2 中从 DateID 4 到 7,然后更改为 StoredID 3,最后它从 DateID 9 回到 StoreID 1 到我们最后一个DateID 范围内的 DateID “已选择”。这就是为什么答案表有 2 行 ParentID 为 1。

4

2 回答 2

0

我终于找到了一个解决方案,它基于我的 Initial Table 比使用 CTE 具有更好的性能,并且由https://stackoverflow.com/users/2522030/mike-abramczyk建议(真实表有 5k 个条目并使用他的建议是需要很长时间)。

查询搜索表后,我在表中为每个 ProductID 添加了两行。这些行将收到一个虚拟 StoreID(即 -9999):一个具有 Min(DateID) - 1,另一个具有 Max(DateID) + 1。

Insert into #Trackings (Aux_Row_Number,StoreID,DateID,ProductID,value)
Select Min(Aux_Row_Number)-1 Aux_Row_Number,-9999 as StoreID, min(DateID)-1 as DateID,ProductID,Min(value)
From #Trackings
group by ProductID
Order by ProductID

Insert into #Trackings (Aux_Row_Number,StoreID,DateID,ProductID,value)
Select Max(Aux_Row_Number)+1 Aux_Row_Number,-9999 as StoreID, max(DateID)+1 as DateID,ProductID,Max(value)
From #Trackings
group by ProductID
Order by ProductID

然后,我使用我发布的查询来获取更改。所以我可以得到从 Dummy(-9999) 到真实 StoreID (1) 的更改以及从真实 StoreID(3) 到 Dummy(-9999) 的最后一次更改。

select      ISNULL(A.StoreID,-1)
,           ISNULL(B.StoreID,-1)
,           A.ProductID
,           A.value
,           B.value
,           A.DateID
,           B.DateID
,           ROW_NUMBER() OVER (Partition by B.ProductID Order by A.DateID)
from            #Trackings A
Join            #Trackings B
On              A.ProductID = B.ProductID
And             A.Aux_Row_Number + 1 = B.Aux_Row_Number
AND             ISNULL(A.StoreID,0) <> ISNULL(B.StoreID ,0)

这是关键的一步!现在我可以使用我正在寻找的更改的 DateID 创建结果表。Aux_Row_Number 列帮助获得对每个产品的更改序列(认为最后一个查询创建了表#ProductStoreChanges - 我将在下面发布整个解决方案):

select              A.ID_FinalStore,A.DateID_Final,B.DateID_Final,A.ProductID,B.value_2,A.value_2,B.value_2 - A.value_2 DeltaValue
from                #ProductStoreChanges A
Join                #ProductStoreChanges B
On                  (A.Aux_Row_Number + 1 = B.Aux_Row_Number) 
And                 A.ProductID = B.ProductID
Order by            A.DateID_Final

这是最终解决方案:

IF OBJECT_ID('tempdb..#Trackings') Is Not Null
    Drop table #Trackings

IF OBJECT_ID('tempdb..#ProductStoreChanges') Is Not Null
    Drop table #ProductStoreChanges

 Create Table #Trackings
 (
   ProductID bigint
 , value    float
 , StoreID  int
 , DateID int
 , Aux_Row_Number int
 , flg_changed bit Default(0)
 )

Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,1,325.2,1)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,2,326.2,2)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,3,329.6,3)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,4,335.2,4)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,5,336.5,5)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,6,338.3,6)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,7,339.2,7)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,8,342.1,8)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,9,343.7,9)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,10,355.0,10)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,12,385.0,12)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,13,485.0,13)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,14,985.0,14)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,15,1585.0,15)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,16,3585.0,16)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,17,5585.0,17)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,18,6585.0,18)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,19,8585.0,19)
Insert into #Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,20,9585.0,20)

Insert into #Trackings (Aux_Row_Number,StoreID,DateID,ProductID,value)
Select Min(Aux_Row_Number)-1 Aux_Row_Number,-9999 as StoreID, min(DateID)-1 as DateID,ProductID,Min(value)
From #Trackings
group by ProductID
Order by ProductID

Insert into #Trackings (Aux_Row_Number,StoreID,DateID,ProductID,value)
Select Max(Aux_Row_Number)+1 Aux_Row_Number,-9999 as StoreID, max(DateID)+1 as DateID,ProductID,Max(value)
From #Trackings
group by ProductID
Order by ProductID

 CREATE TABLE #ProductStoreChanges
 (
            ID_InitialStore         INT
  ,         ID_FinalStore           INT  
  ,         ProductID                   INT
  ,         value_1                 BIGINT 
  ,         value_2                 BIGINT 
  ,         DateID_Initial          BIGINT
  ,         DateID_Final            BIGINT 
  ,         Aux_Row_Number          INT
 )

INSERT INTO #ProductStoreChanges 
(   
            ID_InitialStore
  ,         ID_FinalStore       
  ,         ProductID               
  ,         value_1         
  ,         value_2         
  ,         DateID_Initial
  ,         DateID_Final
  ,         Aux_Row_Number      
)

select      ISNULL(A.StoreID,-1)
,           ISNULL(B.StoreID,-1)
,           A.ProductID
,           A.value
,           B.value
,           A.DateID
,           B.DateID
,           ROW_NUMBER() OVER (Partition by B.ProductID Order by A.DateID)
from            #Trackings A
Join            #Trackings B
On              A.ProductID = B.ProductID
And             A.Aux_Row_Number + 1 = B.Aux_Row_Number
AND             ISNULL(A.StoreID,0) <> ISNULL(B.StoreID ,0)


select              A.ID_FinalStore,A.DateID_Final,B.DateID_Final,A.ProductID,B.value_2,A.value_2,B.value_2 - A.value_2 DeltaValue
from                #ProductStoreChanges A
Join                #ProductStoreChanges B
On                  (A.Aux_Row_Number + 1 = B.Aux_Row_Number) 
And                 A.ProductID = B.ProductID
Order by            A.DateID_Final
于 2013-08-16T21:32:33.147 回答
0

好的,试试这个,使用您更新的示例数据:

Declare @Trackings table
 (
   ProductID bigint
 , value    float
 , StoreID  int
 , DateID int
 , Aux_Row_Number int
 )

Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,1,325.2,1)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,2,326.2,2)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,3,329.6,3)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,4,335.2,4)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,5,336.5,5)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,6,338.3,6)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,7,339.2,7)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,8,342.1,8)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,9,343.7,9)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,10,355.0,10)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,1,12,385.0,12)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,13,485.0,13)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,14,985.0,14)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,15,1585.0,15)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,3,16,3585.0,16)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,17,5585.0,17)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,18,6585.0,18)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,19,8585.0,19)
Insert into @Trackings(ProductID,StoreID,DateID,value,Aux_Row_Number) Values (100,2,20,9585.0,20)
 ;
with t
as (select *, ROW_NUMBER() over (order by dateid) as rn
from @Trackings ),

cte1 
    (Productid, 
    Storeid, 
    DateID,
    value,
    rn,
    set1)
as 
    (select ProductID, StoreID, DateID, value, rn , 1
    from  t
    where rn = 1
union all
    select t.productID, t.storeID, t.dateID, t.value, t.rn, 
    case when 
        cte1.Storeid = t.storeID then cte1.set1 else cte1.set1+1 end
    from  t join cte1 on t.rn = cte1.rn+1)

 ,

t2 as (select Productid, Storeid, set1, MIN(CAST(DateID as int)) as tmi, max(dateid) as tma
from cte1
group by Productid, Storeid, set1)

select t3.Productid, t3.Storeid, t3.set1, t3.date_min, t3.date_max, u.value - t.value
from
(select a.Productid, a.Storeid, a.set1, a.tmi as date_min, coalesce(b.tmi, a.tma) as date_max
from t2 a left join t2 b
on a.set1 + 1 = b.set1) t3 join @Trackings t
on t3.date_min =  t.DateID
join @Trackings u
on t3.date_max = u.DateID
order by set1

“值”列让我感到困惑,因为您使用逗号 (,) 而不是句点 (.) 将整数与浮点数的小数部分分开。

于 2013-08-15T22:52:52.910 回答