0

私は 3 つのテーブルを持っています。もう 1 つの (Price) は、各商品 (Instrument) の毎日の (TradeDate) 終値 ([Close]) を保持します。3 つ目は有用かもしれません。(CalcDate) は、保有を再計算し、ポートフォリオから商品を追加および削除する日付 (CalcDate) を保持します。

SELECT SUM([Close]*Holding), TradeDate 
FROM Price p1 INNER JOIN PortfolioInstrument pio ON pio.Instrument = p1.Instrument 
AND pio.Portfolio = 3 
WHERE EXISTS (SELECT TradeDate FROM Price p 
INNER JOIN PortfolioInstrument pi ON pi.Instrument = p.Instrument AND Portfolio = 3
WHERE TradeDate >= pi.DateAdded AND 
(TradeDate < pi.DateRemoved OR pi.DateRemoved IS NULL) 
AND p1.ID = p.ID GROUP BY TradeDate) GROUP BY TradeDate

PortfolioInstrument データ セットのサンプルを次に示します。

ID  Portfolio Instrument Holding    DateAdded               DateRemoved

16256   3   410     714.28571       2007-10-01 00:00:00.0   2007-11-01 00:00:00.0
16257   3   611     564.97174       2007-10-01 00:00:00.0   2007-11-01 00:00:00.0
16258   3   538     1,797.75281     2007-10-01 00:00:00.0   2007-11-01 00:00:00.0
...
16302   3   5352    1,067,319.75    2008-02-01 00:00:00.0   2008-04-01 00:00:00.0
16303   3   5353    1,057,800.875   2008-02-01 00:00:00.0   2008-04-01 00:00:00.0
16304   3   11952   0               2008-02-29 00:00:00.0   2008-04-01 00:00:00.0
16305   3   11952   261,484,400     2008-04-01 00:00:00.0   2008-05-01 00:00:00.0
...
16315   3   8374    14,199.99902    2009-01-30 00:00:00.0   <null>
16316   3   11952   246,102,960     2009-01-30 00:00:00.0   2009-02-27 00:00:00.0
16317   3   11952   246,148,912     2009-02-27 00:00:00.0   2009-04-01 00:00:00.0

これに関する問題は、DateRemoved < TradeDate を持つすべての所蔵が含まれているため、セットから削除する必要がある再計算日ごとにジャンプが発生することです。Stackoverflow でさまざまな DateDiff メソッドを見てみましたが、この場合、それらを使用してグループ化する方法がわかりません。また、キャッシュ商品 (Instrument = 11952) がある時点でポートフォリオに入り、その後毎月のエントリを取得することに注意してください。数か月間は 0 に減少することがわかりますが、これは問題ではないと思います。生成された SQL では.

どうも。

デビッド

4

2 に答える 2

1

そのような同じ結合の別のインスタンスを使用している理由はあまり明確ではありません。特定の所蔵を除外したい場合DateRemoved <= TradeDateは、WHERE 句で直接確認できます。

SELECT SUM(p1.[Close]*pio.Holding), TradeDate 
FROM Price p1
INNER JOIN PortfolioInstrument pio
ON pio.Instrument = p1.Instrument AND pio.Portfolio = 3 
WHERE p1.TradeDate >= pio.DateAdded
  AND (p1.TradeDate < pio.DateRemoved OR pio.DateRemoved IS NULL) 
GROUP BY p1.TradeDate
;

ただし、少なくとも 1 つの行が条件を満たしている同じ行のグループ全体を破棄する場合は、次のように HAVING 句を使用できます。TradeDateDateRemoved <= TradeDate

SELECT SUM(p1.[Close]*pio.Holding), TradeDate 
FROM Price p1
INNER JOIN PortfolioInstrument pio
ON pio.Instrument = p1.Instrument AND pio.Portfolio = 3 
GROUP BY p1.TradeDate
HAVING COUNT(CASE WHEN p1.TradeDate <= pio.DateRemoved) THEN 1 END) = 0
;

個々の行に適用される WHERE 句とは異なり、HAVING は行のグループに対して評価されます。この場合、COUNT() 関数を使用して、グループ内の行数をカウントしますp1.TradeDate <= pio.DateRemoved。少なくとも 1 つある場合、グループは出力から破棄されます。ここで想定している要件は、そのような行がないことだからです。

于 2013-02-14T18:18:32.520 に答える
0

これを進める方法を見つけることができず、生の行を取得してコードで計算を行うことになりました。

于 2013-02-14T11:12:32.787 に答える