2010-11-19 100 views
1

我有两个表如下所示动态枢轴上SQL数据

主表

ID    keyword_tags 
----------- --------------------------------------------- 
10932  international foo data 

和所需的子表(加入关于ID = fk_id子句)

fk_id  date_value    observ_value 
----------- ----------------------- ---------------------- 
10932  2009-01-01 00:00:00.000 331.888888888 
10932  2008-06-01 00:00:00.000 301.888888888 
10932  2008-01-01 00:00:00.000 321.777777777 
10932  2007-01-01 00:00:00.000 288.449066162 
10932  2006-01-01 00:00:00.000 259.789733887 

输出是

ID  keyword_tags    Latest_Value Latest_Change Annual_Change 
------ ---------------------- ------------- ------------- --------------- 
10932 international foo data 331.888888888 30.000000000 10.111111111 

其他e

Latest_Change = observ_value(of most recent date_value) - observ_value(of next most recent date_value) 
Annual_Change = observ_value(of most recent date_value) - observ_value(of recent date_value - 1 year) 

如何使用sql-server来实现这个功能?

+0

这取决于您使用的RBDMS。 – 2010-11-19 11:22:58

+0

@穆尔基 - 你有什么尝试? – 2010-11-19 11:25:07

+0

@Vash - 即时通讯使用sql server2008 – Mulki 2010-11-19 11:26:05

回答

1

这应该工作:

我创建表作为

create table master_table(
    id   int not null identity(1, 1) 
, keyword_tags nvarchar(127) not null 

, constraint "master_PK" primary key clustered("id")); 

create table child_table(
    id   int not null identity(1, 1) 
, fk_id   int not null 
, date_value datetime not null 
, observ_value float not null 

, constraint "child_PK" primary key clustered("id") 
, constraint "child_FK_fkid" foreign key ("fk_id") 
           references master_table("id")); 

让我们插入一些数据:

insert into master_table select N'international foo data'; 
insert into master_table select N'national baz data'; 

insert into child_table--("fk_id", "date_value", "observ_value") 
select 1, N'2009-01-01T00:00:00.000', 331.888888888 
insert into child_table--("fk_id", "date_value", "observ_value") 
select 1, N'2008-06-01T00:00:00.000', 301.888888888 
insert into child_table--("fk_id", "date_value", "observ_value") 
select 1, N'2008-01-01T00:00:00.000', 321.777777777 
insert into child_table--("fk_id", "date_value", "observ_value") 
select 1, N'2007-01-01T00:00:00.000', 288.449066162 
insert into child_table--("fk_id", "date_value", "observ_value") 
select 1, N'2006-01-01T00:00:00.000', 259.789733887; 


insert into child_table--("fk_id", "date_value", "observ_value") 
select 2, N'2003-07-01T00:00:00.000', 142.0 
insert into child_table--("fk_id", "date_value", "observ_value") 
select 2, N'2002-07-02T00:00:00.000', 123.0 
insert into child_table--("fk_id", "date_value", "observ_value") 
select 2, N'2002-07-01T00:00:00.000', 117.0 
insert into child_table--("fk_id", "date_value", "observ_value") 
select 2, N'2001-01-01T00:00:00.000', 107.0; 

现在到了有趣的部分:

with currRow as (
    select fk_id, MAX(date_value) as currDate 
    from child_table 
    group by fk_id) 
select currRow.fk_id, ct.ID, currRow.currDate, ct.observ_value 
into #currRow 
from currRow 
inner join child_table as ct 
    on ct.date_value = currRow.currDate; 

with lastEntry as (
    select olderRows.fk_id, MAX(olderRows.date_value) as date_value 
    from #currRow as currRow 
    inner join child_table as olderRows 
     on olderRows.fk_id = currRow.fk_id 
     and olderRows.date_value < currRow.currDate 
    group by olderRows.fk_id), 
oneYearAgo as (
    select olderRows.fk_id, MAX(olderRows.date_value) as date_value 
    from #currRow as currRow 
    inner join child_table as olderRows 
     on olderRows.fk_id = currRow.fk_id 
     and olderRows.date_value <= DATEADD(YEAR, -1, currRow.currDate) 
    group by olderRows.fk_id) 
select 
     master_table.* 
    , currRow.ID as currID 
    , currRow.currDate 
, currRow.observ_value as currObservValue 
    , lastData.id as lastPriorID 
    , lastData.date_value as lastPriorDateValue 
    , lastData.observ_value as lastPriorObservValue 
    , oneYearAgoData.id as oneYearAgoID 
    , oneYearAgoData.date_value as oneYearAgoDateValue 
    , oneYearAgoData.observ_value as oneYearAgoObservValue 
from #currRow as currRow 
inner join master_table 
    on master_table.id = currRow.fk_id 
inner join lastEntry 
    on lastEntry.fk_id = currRow.fk_id 
inner join child_table as lastData 
    on lastData.fk_id = lastEntry.fk_id 
    and lastData.date_value = lastEntry.date_value 
inner join oneYearAgo 
    on oneYearAgo.fk_id = currRow.fk_id 
inner join child_table as oneYearAgoData 
    on oneYearAgoData.fk_id = oneYearAgo.fk_id 
    and oneYearAgoData.date_value = oneYearAgo.date_value 

从这些计算您的Latest_Change和Annual_Change留给读者一个练习。

+0

哇......这是一个巨大的查询! – Mulki 2010-11-25 19:05:25

+0

Naaah ...不计算临时表#currRow的创建,它仍然只有一个屏幕。无论如何:你尝试过吗? – 2010-11-26 07:38:04

0

使用以下代码检索一个条目的值更改。您可以通过使用while循环或游标并执行通过使用下面的查询检索到的所有数据的联合来为主表中的多个条目重现此操作。

select fk_id,[1] as current_value,[1] - [2] latest_change,[1]-[3] annual_change 
    from 
      ( 
       select top 2 fk_id,observ_value ,ROW_NUMBER() over (order by date_value desc) row from child_table od 
        where fk_id in(10932) 
       union 
       select fk_id,observ_value,3 row from child_table 
        where fk_id=10932 and date_value =(select DATEADD(YY, -1, MAX(date_value))from child_table where fk_id=10932) 
      )as source_data pivot 
    (
    max(observ_value) for row in ([1],[2],[3]) 
    ) pd   
+0

如果不是绝对必要的,我不会使用循环或游标 - 在这种情况下,它不是。 – 2010-11-26 07:38:58