2012-11-30 8 views
5

これは、例えばクエリです:1行から別の行にクエリ値を取得する方法は?

payment_Type payment_value  cost_type  cost value 
Cost I   100     Registration  40 
Cost I   100     books    40 
Cost I   100     Lab    40 

IがCost_value自分のを持っている3つの要素Cost_Typeを持っていCOST。

私はこのように操作したい:

payment_Type payment_value  cost_type  cost value  Payment_by_cost_type 
Cost I   100     Registration  40    40 
Cost I   100     books    40    40 
Cost I   100     Lab    40    20 

ポイントは、私は各cost_valuepayment_valueを分けたいです。この例では、payment_by_costは40,40,20 = 100になります。

実験室cost_valueは40ですが、上記の分割2コストタイプのままであるため、値は20です。

Payment_by_cost_typeの値を次のレコードに使用できますか?私は一時的なテーブルに値Payment_by_cost_typeを挿入しようとしていますが、selectには挿入ステートメントがありません。

これを解決する方法はありますか?私はDWHに相談してきました。彼はそれがクエリではできないストアプロシージャを使用しなければならないと言いました。あなたは(この例では、私はIDを使用している)ことを行っているたら支払いを注文するあなたの記録を定義するためのいくつかの種類が

を適用する必要が定義する必要が

答えて

2

私はあなたのテーブルにはので、ここだけではなく、「コストI」が、他の値が含まれているテーブル内(PAYMENT_TYPEによる)すべてのグループの出力結果にクエリを推測:

;with table1 as 
(select 
t.*, 
row_number() 
OVER 
(PARTITION BY payment_Type order by cost_type) rn 
from t 
) 
,table2 as 
(select t4.*,isnull((select sum(cost_value) from table1 
    where table1.payment_type=t4.payment_type and rn<t4.rn),0) CumSum 
    from table1 t4 
) 
select payment_type,payment_value,cost_type,cost_value, 
case when cost_value+CumSum<=payment_value then cost_value 
    else 
    payment_value-Cumsum     
    end      

from table2 
order by Payment_type,rn; 

SQLFIDDLE demo

1

...

select * 
    , case 
      when payment_value-(select isnull(SUM(cost_value),0) from yourtable t2 where t2.id<t1.id)<cost_value 
      then payment_value-(select isnull(SUM(cost_value),0) from yourtable t2 where t2.id<t1.id) 
      else cost_value 
      end 
from yourtable t1 
1

一般的なテーブル式を使用して段階的に実行します。

declare @t table (
payment_type varchar(20), 
payment_value int, 
cost_type varchar(20), 
cost_value int, 
cost_id int --for the ordering 
) 

insert @t values 
('Cost I',100,'Registration',40,1), 
('Cost I',100,'books',40,2), 
('Cost I',100,'Lab',40,3), 
('Cost 2',100,'Registration',40,4), 
('Cost 2',100,'books',50,5), 
('Cost 2',100,'Lab',40,6) 

--get count for each payment_type to determine last row 
;with payment_value_cte(payment_type,payment_value,count) as 
(
    select payment_type,payment_value,COUNT(*) from @t group by payment_type,payment_value 
), 
--use sequential index for each row in payment type 
payment_value_index_cte(
    payment_type , 
    payment_value, 
    cost_type, 
    cost_value, 
    cost_id, 
    row) as 
(
    select *,ROW_NUMBER() OVER(PARTITION BY payment_type ORDER BY cost_id) from @t --assumes order is by an id 
), 
--get sum of each row for payment type except last row 
payment_value_sum_except_last_cte(
    payment_type, 
    payment_value, 
    current_sum) as 
(
    select pi.payment_type,pi.payment_value,SUM(cost_value) 
    from payment_value_index_cte pi 
    inner join payment_value_cte pt on pt.payment_type = pi.payment_type 
    where pi.row < pt.count 
    group by pi.payment_type,pi.payment_value 
) 
select 
pi.payment_type,pi.payment_value,pi.cost_type,pi.cost_value, 
--if last row calculate difference, else use the cost_value 
case when pi.row = pt.count then pt.payment_value - pe.current_sum else pi.cost_value end [Payment_by_cost_type] 
from payment_value_index_cte pi 
inner join payment_value_cte pt on pt.payment_type = pi.payment_type 
inner join payment_value_sum_except_last_cte pe on pe.payment_type = pi.payment_type 
1
SELECT payment_Type, payment_value, cost_type, cost_value, 
     CASE WHEN ROW_NUMBER() OVER (ORDER BY(SELECT 1)) = COUNT(*) OVER (PARTITION BY payment_Type) 
      THEN SUM(cost_value) OVER (PARTITION BY payment_Type) - payment_value 
      ELSE cost_value END AS Payment_by_cost_type 
FROM dbo.your_table 

デモ用SQLFiddle

関連する問題