2017-08-18 13 views
1

登録してからユーザーの支払いを含む合計金額があります。 登録日から毎年、ユーザーはプレミアムメンバーシップを支払わなければなりませんが、同じ年に払う必要はありません。ユーザーはeを支払うことができます。例えば。 3年前に戻るまたは、今後3年間は前もって。ユーザーが払うべき値です期間の支払いを分割する

year | rate 
2014 | 100 
2015 | 100 
2016 | 50 
2017 | 150 
2018 | 100 

を次のように年間の

料金です。しかし、必要以上に少ない金額を譲渡することができます。ユーザーが438 $を支払ったとしましょう。彼がこれをしたときは問題ではない。それは2014年または今年になる可能性があります。 2014年から今年までの手数料です。

私がしたいことは、支払われるべきすべてのものがあることを確認するために支払われる必要がある毎年の彼の移転(計算され、変数に格納される)の合計金額を分割することです。私が取得したいと思い

結果:

year | rate | payed 
2014 | 100 | 100 
2015 | 100 | 100 
2016 | 50 | 50 
2017 | 150 | 150 
2018 | 100 | 38 

だから、ユーザーがすべてを払ったことに彼が最新でなければならず、38 $過剰支払いを持っています。

ループ/カーソルを使用することはできますが、使用するウィンドウ機能を考えることはできません。何かヒント?この場合、Googleに問い合わせる方法が見つかりません。

サンプル(ソリューションは、作業が、窓関数と同等を探している)

DECLARE @total DECIMAL = 438 

;WITH data AS 
(
    SELECT *, @total - (SELECT SUM(tt.rate) FROM 
     (VALUES 
     (2013, 100), 
     (2014, 100), 
     (2015, 100), 
     (2016, 100), 
     (2017, 100), 
     (2018, 100)) tt([Year], Rate) 
     WHERE tt.[Year] < t.[Year]) AS Payed 
    FROM (VALUES 
    (2013, 100), 
    (2014, 100), 
    (2015, 100), 
    (2016, 100), 
    (2017, 100), 
    (2018, 100)) t([Year], Rate) 
), 
prepared AS 
(
    SELECT d.[Year], @total AS Total, d.Rate, 
     CASE 
      WHEN ISNULL(d.Payed, d.Rate) <= 0 THEN NULL 
      WHEN @total < d.Rate THEN @total ELSE ISNULL(d.Payed, d.Rate) 
     END AS Payed 
    FROM data d 
) 
SELECT p.[Year], @total AS Total, p.Rate, 
    CASE 
     WHEN p.Payed >= p.Rate THEN p.Rate 
     ELSE p.Payed 
    END Payed 
FROM prepared p 
+1

? "1年ごとの彼の移籍の総額を分けて、彼はすべてが支払われたことを確認する"と言ってください。なぜ私たちは分裂していますか?何が支払われたかを見るために年間の送金額を合計したくないですか?道に迷いました。あなたの質問を明確にするのに役立つテーブルの表示、サンプルデータ、期待される結果を検討してください。 – xQbert

+0

サンプルコードと追加の説明が追加されました – lszk

答えて

1

SQL Server 2012+を使用している場合は、合計未払い額(または過払い金額)をSUM() OVER (ORDER BY...)で計算するのは非常に簡単です。

サンプル・データ

DECLARE @TotalPaid money = 438; 

DECLARE @Rates TABLE (Y int, Rate money); 
INSERT INTO @Rates (Y, Rate) VALUES 
(2014, 100), 
(2015, 100), 
(2016, 50), 
(2017, 150), 
(2018, 100), 
(2019, 100); 

クエリ

WITH 
CTE 
AS 
(
    SELECT 
     Y 
     ,Rate 
     ,SUM(Rate) OVER (ORDER BY Y 
     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS SumRate 
    FROM @Rates 
) 
,CTE2 
AS 
(
    SELECT 
     Y 
     ,Rate 
     ,SumRate 
     ,@TotalPaid - SumRate AS PaidExtra 
    FROM CTE 
) 
SELECT 
    Y 
    ,Rate 
    ,SumRate 
    ,PaidExtra 
    ,CASE WHEN PaidExtra >= 0 
     THEN Rate 
     ELSE Rate + PaidExtra 
    END AS Paid 
FROM CTE2 
ORDER BY Y 
; 

結果から `coming`を払っている

+------+--------+---------+-----------+--------+ 
| Y | Rate | SumRate | PaidExtra | Paid | 
+------+--------+---------+-----------+--------+ 
| 2014 | 100.00 | 100.00 | 338.00 | 100.00 | 
| 2015 | 100.00 | 200.00 | 238.00 | 100.00 | 
| 2016 | 50.00 | 250.00 | 188.00 | 50.00 | 
| 2017 | 150.00 | 400.00 | 38.00  | 150.00 | 
| 2018 | 100.00 | 500.00 | -62.00 | 38.00 | 
| 2019 | 100.00 | 600.00 | -162.00 | -62.00 | 
+------+--------+---------+-----------+--------+ 
0

私は100%に従うが、わからないかもしれないこの:

の作業例:http://rextester.com/OCHHR61883

DECLARE @total DECIMAL = 438 

;WITH data AS 
(
    SELECT *, @total - (SELECT SUM(tt.rate) FROM 
     (VALUES 
     (2013, 100), 
     (2014, 100), 
     (2015, 100), 
     (2016, 100), 
     (2017, 100), 
     (2018, 100)) tt([Year], Rate) 
     WHERE tt.[Year] < t.[Year]) AS Payed 
    FROM (VALUES 
    (2013, 100), 
    (2014, 100), 
    (2015, 100), 
    (2016, 100), 
    (2017, 100), 
    (2018, 100)) t([Year], Rate) 
), 
prepared AS 
(
    SELECT d.[Year], @total AS Total, d.Rate 
      , case when @total-sum(rate) over(Order by year asc)<0 then 0 
       else @total-sum(rate) over(Order by year asc) end as RunningTotal 

    FROM data d 
) 
Select * from prepared 

これは私たちに:

+----+------+-------+------+--------------+ 
| | Year | Total | Rate | RunningTotal | 
+----+------+-------+------+--------------+ 
| 1 | 2013 | 438 | 100 |   338 | 
| 2 | 2014 | 438 | 100 |   238 | 
| 3 | 2015 | 438 | 100 |   138 | 
| 4 | 2016 | 438 | 100 |   38 | 
| 5 | 2017 | 438 | 100 |   0 | 
| 6 | 2018 | 438 | 100 |   0 | 
+----+------+-------+------+--------------+ 

それとも今私が見ていることに近いかもしれないこの:

http://rextester.com/AFR44863

DECLARE @total DECIMAL = 438 

;WITH data AS 
(
    SELECT *, @total - (SELECT SUM(tt.rate) FROM 
     (VALUES 
     (2013, 100), 
     (2014, 100), 
     (2015, 100), 
     (2016, 100), 
     (2017, 100), 
     (2018, 100)) tt([Year], Rate) 
     WHERE tt.[Year] < t.[Year]) AS Payed 
    FROM (VALUES 
    (2013, 100), 
    (2014, 100), 
    (2015, 100), 
    (2016, 100), 
    (2017, 100), 
    (2018, 100)) t([Year], Rate) 
), 
prepared AS 
(
    SELECT d.[Year], @total AS Total, d.Rate 
      , case when @total-sum(rate) over(Order by year asc) > 0 then d.rate 
       when @total-sum(rate) over(Order by year asc) < 0 and sum(rate) over(Order by year asc) > 0 and [email protected](rate) over(Order by year asc) < 0 then 0    
       when @total-sum(rate) over(Order by year asc) < 0 and sum(rate) over(Order by year asc) > 0 then [email protected](rate) over(Order by year asc) 
       end as Paid 

    FROM data d 
) 
Select * from prepared 


+----+------+-------+------+------+ 
| | Year | Total | Rate | Paid | 
+----+------+-------+------+------+ 
| 1 | 2013 | 438 | 100 | 100 | 
| 2 | 2014 | 438 | 100 | 100 | 
| 3 | 2015 | 438 | 100 | 100 | 
| 4 | 2016 | 438 | 100 | 100 | 
| 5 | 2017 | 438 | 100 | 38 | 
| 6 | 2018 | 438 | 100 | 0 | 
+----+------+-------+------+------+ 

または第一クエリに基づいて異なるアプローチ:私たちと同じ結果を与える http://rextester.com/BVSDS50299

DECLARE @total DECIMAL = 438 

;WITH data AS 
(
    SELECT *, @total - (SELECT SUM(tt.rate) FROM 
     (VALUES 
     (2013, 100), 
     (2014, 100), 
     (2015, 100), 
     (2016, 100), 
     (2017, 100), 
     (2018, 100)) tt([Year], Rate) 
     WHERE tt.[Year] < t.[Year]) AS Payed 
    FROM (VALUES 
    (2013, 100), 
    (2014, 100), 
    (2015, 100), 
    (2016, 100), 
    (2017, 100), 
    (2018, 100)) t([Year], Rate) 
), 
prepared AS 
(
    SELECT d.[Year], @total AS Total, d.Rate 
      , case when @total-sum(rate) over(Order by year asc) < 0 then 0 
       else case when @total-sum(rate) over(Order by year asc)> d.rate then d.rate else @total-sum(rate) over(Order by year asc) end end 
    as RunningTotal 

    FROM data d 
) 
Select * from prepared 

2番目のクエリ。

関連する問題