2013-02-07 103 views
0

我有3個表,1(PortfolioInstrument)持有在日期範圍(DateAdded,DateRemoved)中持有(持有)的Portoflio中的工具(工具)。 另一個(價格)每個工具(工具)持有每日(TradeDate)收盤價格([Close])。 第三天可能有用,(CalcDate)包含我們重新計算持有量的日期(CalcDate),並從投資組合中添加和刪除工具。TSQL計算具有重疊日期範圍的記錄的每日總和

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方法,但不能解決在這種情況下如何分組使用它們。另請注意,現金工具(工具= 11952)會在某個時間點進入投資組合,然後每個月都會獲得一個入場點,因爲您可以看到它在幾個月內降至0,這在我所想到的SQL中並不重要。

Thx。

大衛

回答

0

找不到向前這種方式,結束了在原始行拉,做在代碼的計算。

+0

我可以看到我遲到了節目。如果您有機會重新考慮SQL解決方案,請查看我的建議。 –

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 
; 

但是,如果您想放棄同TradeDate行的整個,其中至少一個排滿足條件DateRemoved <= TradeDate,你可以使用一個HAVING子句,像這樣:

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子句,它適用於各行,其爲一組行的評估。在這種情況下,COUNT()函數用於統計組中有多少行有p1.TradeDate <= pio.DateRemoved。如果至少有一個,該組將從輸出中被丟棄,因爲我在這裏假設的要求是不存在這樣的行。