加入两张桌子以获得明天的价格(和“现在”两天的价格)

时间:2009-08-19 00:16:34

标签: sql ms-access

我正在尝试进行JOIN查询来分析一些股票。在我的第一张名为top10perday的表中,我列出了我每天选择“买入”并在第二天卖出的10只股票:

date        symbol
07-Aug-08   PM
07-Aug-08   HNZ
07-Aug-08   KFT
07-Aug-08   MET
...
08-Aug-08   WYE
08-Aug-08   XOM
08-Aug-08   SGP
08-Aug-08   JNJ

例如,记录#1:

  • 记录日期是08年8月7日
  • 我希望在08年8月7日(即08年8月8日)之后的下一个交易日购买一部分PM股票
  • 我希望在 08年8月8日之后的两个交易日内出售该股票,结果是08年8月11日

我的股票价格在一张名为prices的表格中,如下所示:

date        symbol   price
07-Aug-08   PM       54.64
08-Aug-08   PM       55.21
11-Aug-08   PM       55.75
12-Aug-08   PM       55.95
... many more records with trading day, symbol, price

我想做一个JOIN,以便我的结果集如下所示:

date        symbol  price-next-day  price-two-days 
07-Aug-08   PM      55.21           55.75   
...
list one record per date and symbol in table1.

我尝试过这样的事情:

SELECT top10perday.date, top10perday.symbol, Min(prices.date) AS MinOfdate
FROM prices INNER JOIN top10perday ON prices.symbol = top10perday.symbol
GROUP BY top10perday.date, top10perday.symbol
HAVING (((Min(prices.date))>[date]));

我尝试了很多这方面的变体,但我显然没有在正确的路径上,因为结果集在我的top10perday表中显示的最早日期中只包含10行。

我正在使用Microsoft Access。在此先感谢您的帮助! : - )

4 个答案:

答案 0 :(得分:2)

此语法在Access 2003中有效:

SELECT t10.Date, t10.Symbol, p1.date, p1.price, p2.date, p2.price
FROM 
(top10perday AS t10 
  LEFT JOIN prices AS p1 
  ON t10.Symbol = p1.symbol) 
  INNER JOIN prices AS p2 ON t10.Symbol = p2.symbol
WHERE (
((p1.date)=((Select Min([date]) as md 
             from prices 
             where [date]>t10.[Date] and symbol = t10.symbol
            ))
) AND ((p2.date)=((Select Min([date]) as md 
                   from prices 
                   where [date]>p1.[Date] and symbol = t10.symbol)
                 ))
);

这个想法是让第一个(最小)日期大于上一个表格中的日期(top10perday,价格为p1)

答案 1 :(得分:1)

我的猜测是:

SELECT top10perday.date, top10perday.symbol, MIN(pnd.price) AS PriceNextDay, MIN(ptd.price) AS PriceTwoDays 
FROM top10perday 
LEFT OUTER JOIN prices AS pnd ON (pnd.symbol = top10perday.symbol AND pnd.date > top10perday.date) 
LEFT OUTER JOIN prices AS ptd ON (ptd.symbol = top10perday.symbol AND ptd.date > pnd.date) 
GROUP BY top10perday.date, top10perday.symbol
HAVING ((pnd.date = Min(pnd.date) AND ptd.date = Min(ptd.date));

这只是在黑暗中拍摄,但我的理由是:列出你想要的所有股票(top10perday),并为每只股票获得价格(如果存在),在其日期之后的最小日期填充PriceNextDay以及PriceNextDay填充PriceTwoDays后的最小日期价格。表现可能很糟糕。但测试它,看它是否有效。稍后我们可以尝试改进它。

** EDIT **包括Rob Farley的评论。

答案 2 :(得分:1)

这应该只是价格表的三个副本之间的连接。问题是你需要加入到下一个交易日,这是一个稍微棘手的问题,因为它并不总是第二天。所以我们最终会遇到一个更复杂的情况(特别是因为有些日子因节假日而被忽略)。

如果它不是Access,您可以使用row_number()按日期订购价格(每个股票代码使用不同的顺序)。

WITH OrderedPrices AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY symbol ORDER BY date) AS RowNum
FROM Prices
)
SELECT orig.*, next_day.price, two_days.price
FROM OrderedPrices orig
  JOIN
   OrderedPrices next_day
   ON next_day.symbol = orig.symbol AND next_day.RowNum = orig.RowNum + 1
   JOIN
   OrderedPrices two_days
   ON two_days.symbol = orig.symbol AND two_days.RowNum = orig.RowNum + 2
;

但你使用的是Access,所以我认为你没有ROW_NUMBER()。

相反,你可以有一个表格,列出日期,有一个TradingDayNumber ......然后使用它来促进你的加入。

SELECT orig.*, next_day.price, two_days.price
FROM Prices orig
  JOIN
  TradingDays d0
   ON d1.date = orig.date
  JOIN
  TradingDays d1
   ON d1.TradingDayNum = d0.TradingDayNum + 1
  JOIN
  TradingDays d2
   ON d2.TradingDayNum = d0.TradingDayNum + 2
  JOIN
   Prices next_day
   ON next_day.symbol = orig.symbol AND next_day.date = d1.date
   JOIN
   Prices two_days
   ON two_days.symbol = orig.symbol AND two_days.date = d2.date

但显然你需要构建自己的TradingDays表......

罗布

答案 3 :(得分:0)

我不是这次改造的大师,但我可以指出你的想法。尝试在查询中的每个符号的日期列中使用Pivot,从日期到日期。这应该会为您提供一个包含许多列的表格,其中包含您使用日期的名称以及每天的价格。实际上它应该对你在给定时间内拥有的每个股票代码都这样做。

根据你想要绘制的图表,我认为如果你试图绘制股票表现,你会看到VWSP而不仅仅是交易的现货价格会很有趣。