1

私のデータベースは、ユーザーが作成した現金残高、取引、オーバーナイト ポジションに関するものです。日付にもズレがあります。

CTE を使用して、現金と取引の残高合計 [cashtrade_sum] とポジション [pos_sum] を含む 2 つのテーブルを選択しました。以下にサンプルを示します。

cashtrade_sum
-------------
2012-01-30  10000.00
2012-03-19  9868.99
2012-03-20  9839.02
2012-03-21  10476.10
2012-03-22  0.00
2012-03-23  10102.81
2012-03-26  10314.76
2012-03-27  11037.40
2012-03-28  9887.76
2012-03-29  9234.28
2012-03-30  8718.67
2012-04-02  8396.65
2012-04-03  0.00
2012-04-12  0.00
2012-05-18  1796.78

pos_sum
-------
2012-03-22  17628.00
2012-03-23  0.00
2012-03-28  373.24
2012-03-29  0.00
2012-04-03  20835.00
2012-04-04  20736.00
2012-04-05  20268.00
2012-04-06  20268.00
2012-04-07  20268.00
2012-04-08  20268.00
2012-04-09  20412.00
2012-04-10  19998.00
2012-04-11  18999.00
2012-04-12  11465.00
2012-04-13  10975.00
2012-04-14  10975.00
2012-04-15  10975.00
2012-04-16  9750.00

以前の利用可能日の [cashtrade_sum] 値に応じて、各 [pos_sum] 値にコミッション式を適用する必要があります。結果は現在の [cashtrade_sum] 日付に追加する必要があります。したがって、現在の日付 [cashtrade_sum] は、以前の合計または減算に依存します。

明確にするために、現在の [pos_sum] が昨日の [cashtrade_sum] または最大前の利用可能な日付よりも大きい [cashtrade_sum] から各 [pos_sum] 値の 5% を減算する方法を簡単に説明します。[cashtrade_sum] の値が前のステップですでに変更されていると仮定します。

INSERTionsなしでオンザフライでCTEを作成し、5%の手数料値を個別に取得するのを手伝ってください。このような:

results
-------
                    commission  cash
2012-01-30                      10000.00
2012-03-19                      9868.99
2012-03-20                      9839.02
2012-03-21                      10476.10
2012-03-22          881.4       9594.70
2012-03-23          0.00        9594.70
2012-03-28          0.00        9594.70
2012-03-29          0.00        9594.70
2012-04-03          1041.75     8552.95
2012-04-04          1036.80     7516.12
2012-04-05          1013.40     6502.72
...

日付のギャップも埋めた方が良いですが、これは一例です。実際の式ははるかに複雑です。

SQL Server 2008 R2 で実行されています。

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

4

1 に答える 1

2

わかりました、これは私を混乱させました。私はあなたが探しているものを次のように理解していると思いました:

与えられた日ごとに、フィールド "cash" は、cashtrade_sum の値 (存在する場合)、または記録されている最後の日付から Cashtrade_sum を取得し、以前のすべてのコミッション値を差し引いた計算値として定義されます。各日付のコミッションは、pos_sum が前日の現金よりも大きい場合、その日の pos_sum の 5% として定義されます。それ以外の場合、手数料は $0 です。

しかし、実際にそれを実装すると、3 月 23 日、28 日、29 日の Cashtrade_sum 値が結果に反映されていないように見えるため、データは提供された結果の例とはまったく異なります。代わりに、手数料が支払われるとすぐに、cashtrade_bal の後続のすべてのエントリが無視され、現金フィールドは支払われた手数料によってのみ減少するように見えます。

そのため、代わりにそれを実装しましたが、その理由がよくわかりませんでした。また、あなたが言及した日付補間を行うためのカレンダー テーブルも追加したので、毎日の値を取得できます。

CREATE TABLE #cashtrade_sum
(
    recdate date,
    balance money
)

create table #pos_sum
(
    recdate date,
    position money
)

INSERT INTO #cashtrade_sum
VALUES
    ('2012-03-01',  10000.00 ),
    ('2012-03-19',  9868.99 ),
    ('2012-03-20',  9839.02 ),
    ('2012-03-21',  10476.10), 
    ('2012-03-22',  0.00 ),
    ('2012-03-23',  10102.81 ),
    ('2012-03-26',  10314.76 ),
    ('2012-03-27',  11037.40 ),
    ('2012-03-28',  9887.76 ),
    ('2012-03-29',  9234.28 ),
    ('2012-03-30',  8718.67 ),
    ('2012-04-02',  8396.65), 
    ('2012-04-03',  0.00 ),
    ('2012-04-12',  0.00 ),
    ('2012-05-18',  1796.78)

INSERT INTO #pos_sum
VALUES
    ('2012-03-22',  17628.00), 
    ('2012-03-23',  0.00),
    ('2012-03-28',  373.24), 
    ('2012-03-29',  0.00 ),
    ('2012-04-03',  20835.00 ),
    ('2012-04-04',  20736.00 ),
    ('2012-04-05',  20268.00 ),
    ('2012-04-06',  20268.00 ),
    ('2012-04-07',  20268.00 ),
    ('2012-04-08',  20268.00 ),
    ('2012-04-09',  20412.00 ),
    ('2012-04-10',  19998.00 ),
    ('2012-04-11',  18999.00 ),
    ('2012-04-12',  11465.00 ),
    ('2012-04-13',  10975.00 ),
    ('2012-04-14',  10975.00 ),
    ('2012-04-15',  10975.00) ,
    ('2012-04-16',  9750.00)

CREATE TABLE #cal
(
    caldate date
)

DECLARE @CurDate date = '2012-03-01';

while @CurDate < '2012-05-01'
BEGIN
    INSERT INTO #cal
    VALUES(@CurDate)

    SELECT @CurDate = DATEADD(day,1,@CurDate)
END

SELECT * FROM #cashtrade_sum;
SELECT * FROM #pos_sum;
SELECT * FROM #cal;

WITH calc AS
(
    SELECT caldate AS calcdate, CAST(0 AS money) AS commission, balance AS dailybal, balance AS runningbal, CAST(0 as money) as position,
        0 as commpaid
    FROM #cal
        left join #cashtrade_sum
            on #cal.caldate = #cashtrade_sum.recdate
    WHERE caldate = (SELECT MIN(caldate) FROM #cal)

    UNION ALL

    SELECT #cal.caldate, 
        comm.commission,
        cts.balance,
        case 
            when prev.commpaid = 1 OR comm.commission > 0 
                then prev.runningbal - comm.commission
            else 
                ISNULL(cts.balance, prev.runningbal - comm.commission) 
        END,
        ps.position,
        CASE WHEN comm.commission > 0 then 1 else prev.commpaid end
    FROM #cal
        outer apply (SELECT * FROM #pos_sum where #cal.caldate = #pos_sum.recdate) ps
        outer apply (SELECT * FROM #cashtrade_sum where #cal.caldate = #cashtrade_sum.recdate) cts
        cross apply (select runningbal, commpaid from calc where calcdate = DATEADD(DAY, -1, #cal.caldate)) prev
        cross apply (select CASE WHEN prev.runningbal < ps.position THEN cast(ps.position * 0.05 as money) ELSE cast(0 as money) END AS commission) comm
)
SELECT calcdate, commission, runningbal FROM calc

drop table #cashtrade_sum
drop table #pos_sum
drop table #cal

最初の日付を 1 月から 3 月に変更したことに注意してください。これは、SQL Server には既定の再帰制限があり、データが 100 日経過するとこの再帰 CTE が無効になるためです。これをより長い期間機能させるには、再帰制限を上げる必要があります。

結果が実際にどのように見えるべきかについて、あなたか私はまだ混乱していると思いますが、これはあなたが求めた結果を生成します.

于 2012-06-12T04:51:16.507 に答える