2017-11-16 9 views
2

たとえば、C#コードで解決するのは非常に簡単ですが、SQLクエリに書き込む方法はわかりません。ここでSQL Serverでのスライディングウィンドウの機能、高度な計算

は状況です:のは、私は3列(ID, Date, Amount)を持つテーブルを持っており、ここでいくつかのデータであるとしましょう:

ID Date   Amount 
----------------------- 
1 01.01.2016 -500 
2 01.02.2016 1000 
3 01.03.2016 -200 
4 01.04.2016  300 
5 01.05.2016  500 
6 01.06.2016 1000 
7 01.07.2016 -100 
8 01.08.2016  200 

私はテーブルから取得したい結果は、この(ID, Amount .... Order By Date)です。

ID Amount 
----------------------- 
2 300 
4 300 
5 500 
6 900 
8 200 

アイデアは分割払いに金額を分配することですが、負の量は、あなたが最後の分割払いの量を削除する必要が戦場に出たときのことです。私はどれくらい明確であるかわからないので、ここに例があります:

私は3つの請求書が500、200、-300であるとしましょう。

私はこれらの請求書を配布し始めると、まず500から200の金額を配達します。しかし、私が3番目の-300に来たら、最後の請求書から削除する必要があります。他のワークス200 - 300 = -100では、2番目の請求書の金額は消えますが、最初の請求書から差し引かれる必要がある-100が残ります。したがって、500 - 100 = 400です。必要な結果は、1行のデータセット(最初の請求書と金額400)です。

最初の請求書がマイナス金額(-500,300,500)の場合の別の例です。 この場合、最初の( - 500)請求書は2番目の請求書を消滅させ、別の200を3番目のものから引き落とします。したがって、結果は次のようになります。第3インボイス(金額300)

これはプログラミング言語のスタック実装のようなものですが、SQL Serverのスライディングウィンドウ関数で作成する必要があります。

誰かが何か考えている場合は、共有してください。

ありがとうございました。

+0

なぜ '300'に等しい '2'の' amount'です。あなたの説明によると、それは '500'(=' -500 + 100')か、そうでないかもしれませんか? –

+0

2の実数は1000ですが、実際は1000(2)-500(1)-200(3)= 300 負の金額は前の金額から差し引く必要がありますが、量は負であり、それはそれの後ろに来る最初の陽性から差し引かれなければならない –

+0

私は第2の行が '4 | 300'であり、第3の行は' 5 | 500'であると信じます –

答えて

1

私はTSQLを使用して解決しました。しかし、再帰的なCTEを使用してこのタスクも解決できると思います。 IDを使用して、前または次の行を検索しました。

-- create and fill test table 
CREATE TABLE Invoices(
    ID int, 
    [Date] date, 
    Amount float 
) 

INSERT Invoices(ID,Date,Amount) VALUES 
(1,'20160101', -500), 
(2,'20160201', 1000), 
(3,'20160301', -200), 
(4,'20160401', 300), 
(5,'20160501', 500), 
(6,'20160601', 1000), 
(7,'20160701', -100), 
(8,'20160801', 200) 

私のソリューション

-- copy all the data into temp table 
SELECT * 
INTO #Invoices 
FROM Invoices 

DECLARE 
    @nID int, 
    @nAmount float, 
    @pID int 

-- run infinity loop 
WHILE 1=1 
BEGIN 

    -- set all the variables to NULL 
    SET @nID=NULL 
    SET @nAmount=NULL 
    SET @pID=NULL 

    -- get data from the last negative row 
    SELECT 
    @nID=ID, 
    @nAmount=Amount 
    FROM 
    (
     SELECT TOP 1 * 
     FROM #Invoices 
     WHERE Amount<0 
     ORDER BY ID DESC 
    ) q 

    -- get prev positive row 
    SELECT @pID=ID 
    FROM 
    (
     SELECT TOP 1 * 
     FROM #Invoices 
     WHERE ID<@nID 
     AND Amount>0 
     ORDER BY ID DESC 
    ) q 

    IF(@pID IS NULL) 
    BEGIN 
    -- get next positive row 
    SELECT @pID=ID 
    FROM 
     (
     SELECT TOP 1 * 
     FROM #Invoices 
     WHERE ID>@nID 
      AND Amount>0 
     ORDER BY ID 
    ) q 
    END 

    -- exit from loop 
    IF(@pID IS NULL) BREAK 

    -- substract amount from positive row 
    UPDATE #Invoices 
    SET 
    [email protected] 
    WHERE [email protected] 

    -- delete used negative row 
    DELETE #Invoices 
    WHERE [email protected] 

END 

-- show result 
SELECT * 
FROM #Invoices 

DROP TABLE #Invoices 
+0

私はそれがうまくいくと思いますが、要件で私はサイクルがオプションではありません。スライディング関数または再帰的なCTE。 もう一つのことは、これは一人のクライアントのための例です。私はパーティーをしてクライアントなどで請求書をグループ化できるようにする必要があります。だから私はどう考えているのですか? –

+0

@ CrazyStuff27 。 。あなたが尋ねた質問に答えることは可能です。これがあなたの質問に答えるなら、答えを受け入れるべきです。別の質問がある場合は、コメントではなく別の質問として質問してください。 –

+0

@GordonLinoffあなたは正しいです、私は次回より具体的な質問をします。入力いただきありがとうございます。 –