获取结果集中的最高值和最后一个值之间的差异

时间:2015-03-11 06:31:22

标签: sql-server

我的表格看起来像

deal_id   test_value    run_date
820117648   1.2     2014-03-31
820117648   1.33    2014-04-30
820117648   1.33    2014-05-30
820117648   1.26    2014-06-30
820117648   1.11    2014-07-31
820117648   0.58    2014-09-30
820117648   1.64    2014-10-31
820117648   0.64    2014-11-28
820117648   3.65    2014-12-31
820117648   3.8     2015-03-11

820117649   0.64    2014-09-31
820117649   0.23    2014-10-31
820117649   0.64    2014-11-28
820117649   3.65    2014-12-31
820117649   3.8     2015-03-11


SELECT deal_id,test_value,run_date  FROM  ems.cdotests
  WHERE run_date >= Dateadd(month, -4 Getdate())

我试图从整个集合中获取最后4个run_date记录然后 我需要找到我的选择标准的第一个rundate和最后一个rundate之间的testValue之间的差异,即deal_id 820117649 3.8 - 0.23 = 3.57和deal_id 820117648应该是3.8 -1.64 = 2.16 这是一个包含多个交易ID和几个与每个dealid相关联的run_date的大表,可能包含过去15年左右的数据 任何建议都会非常有帮助

3 个答案:

答案 0 :(得分:1)

试试这个解决方案。它不受特定deal_id的约束。

DECLARE @t TABLE ( ID INT, V MONEY, D DATE )

INSERT  INTO @t
VALUES  ( 1, 1, '20140101' ),
        ( 1, 4, '20140102' ),
        ( 1, 2, '20140103' ),
        ( 1, 7, '20140104' ),
        ( 2, 5, '20140104' ),
        ( 2, 8, '20140110' ),
        ( 2, 11, '20140105' );

WITH    cte
          AS ( SELECT   ID ,
                        D ,
                        V ,
                        MIN(D) OVER ( PARTITION BY ID ORDER BY D ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS Min ,
                        MAX(D) OVER ( PARTITION BY ID ORDER BY D ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS Max
               FROM     @t
             )
    SELECT  c1.ID ,
            c2.V - c1.V AS V
    FROM    cte c1
            JOIN cte c2 ON c1.ID = c2.ID AND c1.D < c2.D
    WHERE   ( c1.D = c1.MIN OR c1.D = c1.MAX ) AND ( c2.D = c2.MIN OR c2.D = c2.MAX )

输出:

ID  V
1   6.00
2   3.00

你已经改变了你的问题。最近6个月,在主CTE上方添加过滤器CTE:

;WITH    filter
          AS ( SELECT   ID ,
                        D ,
                        V ,
                        ROW_NUMBER() OVER ( PARTITION BY ID ORDER BY D DESC ) AS RN
               FROM     @t
             ),
        cte
          AS ( SELECT   ID ,
                        D ,
                        V ,
                        MIN(D) OVER ( PARTITION BY ID ORDER BY D ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS Min ,
                        MAX(D) OVER ( PARTITION BY ID ORDER BY D ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS Max
               FROM     filter
               WHERE    RN <= 6
             )
    SELECT  c1.ID ,
            c2.V - c1.V AS V
    FROM    cte c1
            JOIN cte c2 ON c1.ID = c2.ID AND c1.D < c2.D
    WHERE   ( c1.D = c1.MIN OR c1.D = c1.MAX ) 
            AND ( c2.D = c2.MIN OR c2.D = c2.MAX ) 
            AND (c2.V - c1.V > 5)

答案 1 :(得分:0)

您可以使用窗口功能

WITH C AS(
    SELECT ROW_NUMBER() OVER (PARTITION BY deal_Id ORDER BY deal_Id) Rn
           ,deal_Id
           ,test_value
           ,run_date
    FROM ems.cdotests
)
SELECT id1 deal_id, t2 - t1 diff
FROM (SELECT c1.deal_id id1
             ,c1.test_value t1
             ,c2.deal_id id2
             , c2.test_value t2
      FROM C c1 
      INNER JOIN C c2 ON c1.deal_id = c2.deal_id
      WHERE c1.Rn = 1
      AND c2.Rn = (SELECT TOP 1 MAX(Rn) FROM C GROUP BY deal_id)
     ) t

答案 2 :(得分:0)

回答这么晚,但有一种方法是这样的:

;with t as (
    select *, 
        row_number() over (partition by deal_id order by run_date desc) seq
    from ems.cdotests 
)
select 
    t1.deal_id, t1.run_date run_date1, t1.test_value test_value1, 
                t2.run_date run_date4, t2.test_value test_value4, 
    t1.test_value - t2.test_value diff
from t t1
join t t2
  on t1.deal_id = t2.deal_id
where t1.seq = 1
  and t2.seq = 4
  -- as an extra condition of those should have at least 5 records:
  and exists (select 1 from t ti where ti.deal_id = t1.deal_id and ti.seq > 5)

[SQL Fiddle]