2016-05-05 17 views
0

の積は、データセットと私は非常に最初の行のLinkedValueが等しくなるSQL計算現在の行の列の値と前の行計算カラム値以下

ID Postdate Return LinkedValue 
------------------------------ 
1001 7/1/2013 100  100 
1001 7/2/2013 101  101 
1001 7/3/2013 102  102*101/100 
1001 7/4/2013 103  103*102*100/100 

を使用して行う必要があり、計算の一種でありますその後の各行については、前の行について計算された現在の行およびLinkedValueの戻り値の積となります。

これを行う方法はありますか?

+2

どのようなrdbmsを使用していますか? –

+0

ウィンドウ関数としてカスタム集計を使用するのは簡単です。どのように行の順序を定義しますか?リレーショナルデータベースでは、「注文する」ものがない限り、「最初の行」というものはありません。あなたの例の行の順序は 'postdate'列によって定義されていますか?または別の列ですか? –

+1

この例は明確ではありません。 LinkedValuesは100,10100,1030200,106110600のいずれかですか? – knagaev

答えて

0

私は、これはあなたが探しているものだと思う:

WITH cte_prep 
      AS (
       SELECT 
        [rowid] 
       , [ID] 
       , [Postdate] 
       , [Return] 
       , RANK() OVER (PARTITION BY ID ORDER BY Postdate) AS P_Rank 
       FROM 
        [meta].[dbo].[return] 
      ), 
     cte_recursive (ID, Postdate, [Return], P_Rank, preturn, string, Level) 
      AS (
       -- Anchor member definition 
    SELECT 
      e.ID 
     , e.Postdate 
     , e.[Return] 
     , e.P_Rank 
     , 10 AS preturn 
     , CAST(e.[return] AS NVARCHAR(MAX)) AS string 
     , 0 AS Level 
     FROM 
      cte_prep AS e 
     WHERE 
      e.P_Rank = 1 
       UNION ALL 
-- Recursive member definition 
       SELECT 
        e.ID 
       , e.Postdate 
       , e.[Return] 
       , e.P_Rank 
       , d.[return] AS preturn 
       , CAST(d.string + ' * ' + CAST(e.[return] AS NVARCHAR(50)) AS NVARCHAR(MAX)) AS string 
       , Level + 1 AS Level 
       FROM 
        cte_prep AS e 
       INNER JOIN cte_recursive AS d 
       ON e.ID = d.ID AND 
        e.P_rank = d.P_rank + 1 
      ) 
    SELECT 
      * 
     FROM 
      cte_recursive 

The results look like this

0

これは、窓関数としての乗算集計を使用して非常に簡単です。

DBMSを指定していないため、以下はPostgreSQLです。

テストテーブルを作成します。

create table adi (id integer, postdate date, return integer); 

insert into adi (id, postdate, return) 
    values 
(1001, date '2013-07-01', 100), 
(1001, date '2013-07-02', 101), 
(1001, date '2013-07-03', 102), 
(1001, date '2013-07-04', 103); 

すべての値を乗算集合体を作成する:

create aggregate mult(bigint) 
(
    sfunc = int8mul, 
    stype=bigint 
); 

我々は数字の行とは最初の行のreturn値を保持することの結果を必要とします。

id | postdate | return | linkedvalue 
-----+------------+--------+------------ 
1001 | 2013-07-01 | 100 |   100 
1001 | 2013-07-02 | 101 |  101.00 
1001 | 2013-07-03 | 102 |  103.02 
1001 | 2013-07-04 | 103 | 10611.06 

クエリ:

with numbered as (
    select id, 
     postdate, 
     return, 
     row_number() over (order by postdate) as rn, 
     first_value(return) over (order by postdate) as base_value 
    from adi 
) 
-- only get the first row, so that the return value of that 
-- is not included in the running aggregate 
select id, 
     postdate, 
     return, 
     return as linkedvalue 
from numbered 
where rn = 1 

union all 

select id, 
     postdate, 
     return, 
     (mult(return) over (order by postdate))::numeric/(case when rn > 2 then base_value else 1 end) 
from numbered 
where rn > 1; 

これは、次の結果を返します。私たちは、最終的なクエリを作成することができ、この結果で

select id, 
     postdate, 
     return, 
     row_number() over (order by postdate) as rn, 
     first_value(return) over (order by postdate) as base_value 
from adi 

:これは、ウィンドウ関数を使用して行うことができますカスタム集計関数を除いて、ほとんど標準のANSI SQLです。使用しているDBMSの定義方法は、そのDBMSによって異なります。

カスタム集計を作成できない場合、これは再帰的なCTEを使用して行うことができます。以下は、製品固有の構文を使用しない標準ANSI SQLです。

with recursive numbered as (
    select id, 
     postdate, 
     return, 
     row_number() over (order by postdate) as rn, 
     first_value(return) over (order by postdate) as base_value 
    from adi 
), calc as (
    select id, postdate, return, return as linkedvalue, base_value, rn 
    from numbered 
    where rn = 1 
    union all 
    select c.id, c.postdate, c.return, 
     case when c.rn > 2 then (c.return * p.linkedvalue) else c.return end, 
     p.base_value, 
     c.rn 
    from numbered c 
    join calc p on c.rn - 1 = p.rn 
    where c.rn > 1 
) 
select id, postdate, return, 
     case when 
      rn > 2 then cast(linkedvalue as numeric)/100 
      else linkedvalue 
     end as linkedvalue 
from calc 
order by postdate; 
関連する問題