0

我有 3 个表,1 个(PortfolioInstrument)持有在一个投资组合中持有的工具(Instrument),持有(Holding)跨越一个日期范围(DateAdded,DateRemoved)。另一个 (Price) 持有每种工具 (Instrument) 的每日 (TradeDate) 收盘价 ([Close])。第三个可能有用,(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 的 Holdings,因此每个重新计算日期都会有一个跳转,它们应该从集合中删除。查看了 Stackoverflow 上的各种 DateDiff 方法,但无法弄清楚在这种情况下如何使用它们进行分组。另请注意,现金工具(Instrument = 11952)在某个时候进入投资组合,然后每个月都获得一个条目,正如您所看到的那样,它在几个月内减少到 0,我认为在生成的 SQL 中这无关紧要.

谢谢。

大卫

4

2 回答 2

1

目前还不是很清楚为什么要使用相同连接的另一个实例。如果您想排除特定的藏品 where 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
;

但是,如果要丢弃至少一行满足条件的一整相同行,则可以使用 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。如果至少有一个,则该组将从输出中丢弃,因为我在这里假设的要求是没有这样的行。

于 2013-02-14T18:18:32.520 回答
0

找不到解决方法,最终拉入原始行并在代码中进行计算。

于 2013-02-14T11:12:32.787 回答