【问题标题】:SQL Server Cross Apply on itself + Cross Apply performance issuesSQL Server 自身交叉应用 + 交叉应用性能问题
【发布时间】:2015-08-03 16:10:38
【问题描述】:

我有以下几点:

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 行。 但是,当我尝试将我的解决方案应用于这 387 行结果时,我的查询返回了正确的结果,但需要 21 秒而不是 3 秒。

有什么改进的建议吗?

还有一点谜题:

  1. 第一个可用的“交易”决定我是多头还是空头

  2. 另一个更复杂的问题(对于喜欢拼图的人)是采用平均加权持股来决定我在此期间是多头还是空头。例如,假设在 19 日最后一次苹果交易后,我还剩 0 个苹果,我又卖出了 100 万个苹果。这意味着从 5 月 19 日到 31 日,我的资金不足 100 万。 (31-19) * -1,000,000

【问题讨论】:

  • 您使用的是哪个 SQL 服务器?
  • SQL Server 2008 R2 Service Pack 2 10.50.4000
  • 通过 SQL Fiddle 运行,这似乎不会生成您想要的结果...sqlfiddle.com/#!3/ea1c3/1/0
  • 感谢您的链接。那是很酷的东西!我看了看,生成的结果是正确的。我在月初(或 5 月的第一个可用交易日期)购买了 150,000 个苹果,因此所有后续的苹果交易都标记为 long。与梨相同(220,000 是第一笔交易,因此所有其他交易都标记为长)
  • 编辑:我应该改写:“好的一开始我有 150,000 个苹果,因此我的整体苹果位置很长”到“好的一开始我有 150,000 个苹果,因此我当时的整体苹果period 是 LONG,因此所有交易(+ve 或 -ve)都应该有“LONG”标记”

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


【解决方案1】:

您交叉应用选择缺少订单截止日期(日期?)。它不是确定性的,也不能保证您确实会获得第一条记录。

在你的样本数据上,这个查询有一个更好的查询计划:

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 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多