2010-11-19 13 views
1

Ich habe zwei Tabellen wie untenDynamische Pivot auf SQL-Daten

Die Master-Tabelle

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

und ein Kind Tisch (Join-Klausel auf 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 

gezeigt Output erforderlich ist

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

wo 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) 

Wie erreiche ich dies mit SQL-Server?

+0

Das hängt von dem RBDMS ab, das Sie verwenden. –

+0

@Mulki - was hast du probiert? –

+0

@Vash - ich benutze sql server2008 – Mulki

Antwort

1

Dies sollte funktionieren:

erstelle ich die Tabellen

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")); 

die einige Daten Lassen einfügen:

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; 

Nun zum interessanten Teil:

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 

Berechnung Ihrer Latest_Change und Annual_Change von diesen wird als Übung für den Leser überlassen.

+0

whoa ... das ist eine riesige Abfrage! – Mulki

+0

Naaah ... die Erstellung der Temp-Tabelle #currRow nicht mitgerechnet, es ist immer noch nur ein einziger Bildschirm. Wie auch immer: Hast du es versucht? –

0

Verwenden Sie den folgenden Code, um die Änderung der Werte für einen Eintrag abzurufen. Sie können dies für mehrere Einträge in der Mastertabelle reproduzieren, indem Sie eine while-Schleife oder einen Cursor verwenden und eine Vereinigung aller Daten ausführen, die mit der folgenden Abfrage abgerufen wurden.

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

Ich würde keine Schleifen oder Cursor verwenden, wenn es nicht absolut notwendig ist - und in diesem Fall ist es nicht. –