2010-11-19 4 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 

Выход требуется is

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

wher 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-сервера?

+0

Это зависит от используемого вами RBDMS. –

+0

@Mulki - что ты пробовал? –

+0

@Vash - im using sql server2008 – Mulki

ответ

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

whoa ... это один огромный запрос! – Mulki

+0

Naaah ... не считая создания таблицы temp #currRow, это все еще только один экран. В любом случае: вы попробовали? –

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

Я бы не использовал циклы или курсоры, если это не совсем необходимо - и в этом случае это не так. –

Смежные вопросы