SQL Server交叉应用自身+交叉应用性能问题

时间:2015-08-03 16:10:39

标签: sql sql-server-2008-r2 recursive-query cross-apply

我有以下内容:

CREATE TABLE #MASTER_POSANDTRANS (ID CHAR(30), 
                                  QUANTITY INT, 
                                  START_OR_TRADE_DATE DATE) 

VALUES 
    ('APPLES ','150000','20150501'), ('PEARS','220000','20150501'), 
    ('APPLES ','-75000','20150506'), ('APPLES ','-65000','20150508'), 
    ('APPLES ','10000','20150516'),  ('APPLES ','-20000','20150519'
    ('PEARS','-110000','20150506'),  ('PEARS','-100000','20150519')

我希望能够说"一开始我有150,000个苹果,因此我的整体苹果位置很长"

以下是我目前正在解决的这个小谜题:

SELECT 
    MPT.ID, 
    MPT.QUANTITY, 
    MPT.START_OR_TRADE_DATE, 
    APPLY_RES.QUANTITY as 'FIRST AVAILABLE  QUANTITY', 
    CASE 
       WHEN APPLY_RES.QUANTITY > 0 
         THEN 'LONG' 
         ELSE 'SHORT' 
    END as 'L/S Indicator'
FROM 
    #MASTER_POSANDTRANS as MPT 
CROSS APPLY
    (SELECT TOP 1 
         MPT_APPLY.QUANTITY 
     FROM 
         #MASTER_POSANDTRANS as MPT_APPLY
     WHERE 
         MPT_APPLY.ID = MPT.ID) APPLY_RES

提供的表是,简化了多个查询的结果,并在大约3秒内吐出大约387行的联合alls。 但是,当我尝试将我的解决方案应用于此387行结果时,我的查询返回正确的结果,但需要21秒而不是3秒。

有任何改进建议吗?

谜题更多:

  1. 第一个可用的"交易"决定我是长还是短

  2. 另一个更复杂的问题(对于那些喜欢谜题的人)是采取平均加权控制来决定在此期间我是长还是短。例如,想象一下,在19号的最后一次苹果交易之后,我剩下0个苹果,我卖掉了另外100万个苹果。这意味着从5月19日到31日,我只有100万。 (31-19)* -1,000,000< (19-1)*(本月出售/购买的苹果的平均数)因此我在那个月持有苹果可被认为是短期的。如果在任何时候两者平衡,我会采用第1点的值。

1 个答案:

答案 0 :(得分:0)

您交叉申请选择缺少订单方式(日期?)。这不是确定性的,也不能保证你确实会获得第一记录。

在您的示例数据上,此查询具有更好的查询计划:

SELECT
    MPT.ID,
    MPT.QUANTITY,
    MPT.START_OR_TRADE_DATE
    , APPLY_RES.QUANTITY as 'FIRST AVAILABLE  QUANTITY',
    CASE
    WHEN APPLY_RES.QUANTITY > 0
        THEN 'LONG'
    ELSE 'SHORT'
    END as 'L/S Indicator'
From MASTER_POSANDTRANS AS MPT
Inner Join (
    Select ID, QUANTITY, N = ROW_NUMBER() over (Partition by ID order by START_OR_TRADE_DATE)
    From MASTER_POSANDTRANS
) as APPLY_RES on APPLY_RES.ID = MPT.ID
Where APPLY_RES.N = 1
--Order By MPT.ID, MPT.START_OR_TRADE_DATE