子选择中的外表引用

时间:2014-10-09 22:47:02

标签: sql sql-server sql-server-2005

我有两张表,一张代表股票交易:

吸墨纸

TradeDate    Symbol   Shares    Price
2014-09-02   ABC      100       157.79
2014-09-10   ABC      200       72.50
2014-09-16   ABC      100       36.82

和存储所有符号的股票拆分历史记录:

拆分

SplitDate    Symbol   Factor
2014-09-08   ABC      2
2014-09-15   ABC      2
2014-09-20   DEF      2

我正在尝试编写一份反映交易的报告,并包括他们当前的拆分调整因子应该是什么。对于这些表值,我希望报告看起来像:

TradeDate    Symbol   Shares   Price    Factor
2014-09-02   ABC      100      157.79   4
2014-09-10   ABC      200      72.50    2
2014-09-16   ABC      100      36.82    1

第一列直接取自 Blotter - 因子应代表自交易发生以来发生的拆分调整( Price 未进行拆分调整)。 使问题复杂化的是每个符号可能有多个分裂,这意味着我不能只OUTER JOIN Splits 表,否则我将开始复制行。

我有一个子查询,我从https://stackoverflow.com/a/3912258/3063706改编,允许我计算行的乘积,按符号分组,但我怎么只返回所有 Splits 记录的产品在 TradeDate 之后发生 SplitDates

类似以下的查询

SELECT tb.TradeDate, tb.Symbol, tb.Shares, tb.Price, ISNULL(s.Factor, 1) AS Factor
    FROM Blotter tb
    LEFT OUTER JOIN (
        SELECT Symbol, EXP(Factor) AS Factor
            FROM
                (SELECT Symbol, SUM(LOG(ABS(NULLIF(Factor, 0)))) AS Factor
                    FROM Splits s
                    WHERE s.SplitDate > tb.TradeDate   -- tb is unknown here
                    GROUP BY Symbol
                ) splits) s 
         ON s.Symbol = tb.Symbol

返回错误“消息4104,级别16,状态1,行1多部分标识符”tb.TradeDate“无法绑定。”

如果没有内部WHERE子句,我会得到如下结果:

TradeDate    Symbol   Shares   Price    Factor
2014-09-02   ABC      100      157.79   4
2014-09-10   ABC      200      72.50    4
2014-09-16   ABC      100      36.82    4

更新 Blotter 中的交易行不保证是唯一的,因此我认为使用GROUP BY排除一个建议的解决方案。

1 个答案:

答案 0 :(得分:1)

不过多改变逻辑的一种方法是将因子计算放入表值函数中:

create function dbo.FactorForDate(
    @Symbol char(4), @TradeDate datetime
) returns table as
return (
    select
        exp(Factor) as Factor
    from (
        select
            sum(log(abs(nullif(Factor, 0)))) as Factor
        from
            Splits s 
        where
            s.SplitDate > @TradeDate and
            s.Symbold = @Symbol
    ) splits
);

select
    tb.TradeDate, 
    tb.Symbol, 
    tb.Shares, 
    tb.Price, 
    isnull(s.Factor, 1) as Factor
from
    Blotter tb
        outer apply
    dbo.FactorForDate(tb.Symbol, tb.TradeDate) s;

在单个语句中执行此操作将类似于:

select
    tb.TradeDate, 
    tb.Symbol, 
    tb.Shares, 
    tb.Price, 
    isnull(exp(sum(log(abs(nullif(factor, 0))))), 1) as Factor
from
    Blotter tb
        left outer join
    Symbol s
         on s.Symbol = tb.Symbol and s.SplitDate > tb.TradeDate
group by
    tb.TradeDate, 
    tb.Symbol, 
    tb.Shares, 
    tb.Price;

如果能让它发挥作用,这可能会表现得更好。

对于任何语法错误道歉,目前无法访问SQL。