tsql确定价格趋势

时间:2012-11-02 16:01:29

标签: tsql grouping

我有一个包含3列的表

+---------------+-------------------------+-------+
| InstrumentId  |          Date           | Price |
+---------------+-------------------------+-------+
|            39 | 2012-10-31 00:00:00.000 |   150 |
|            39 | 2012-11-01 00:00:00.000 |   160 |
|            39 | 2012-11-01 00:00:00.000 |   200 |
|            40 | 2012-10-31 00:00:00.000 |   150 |
|            40 | 2012-11-01 00:00:00.000 |   140 |
|            40 | 2012-11-01 00:00:00.000 |   200 |
|            50 | 2012-10-31 00:00:00.000 |   150 |
|            50 | 2012-11-01 00:00:00.000 |   150 |
|            50 | 2012-11-01 00:00:00.000 |   150 |
+---------------+-------------------------+-------+

我需要回顾下一个结果:

+--------------+-------+
| InstrumentId | Price |
+--------------+-------+
|           39 |   200 |
|           40 |     0 |
|           50 |   150 |
+--------------+-------+

规则: 如果同一InstrumentId的价格正在增长或相等=>返回最后价格(这意味着每个下一个价格大于或等于之前的价格。 例如Id 39:150< = 160< = 200 =>返回200) 如果同一InstrumentId的任何价格低于previous =>返回0(见instrumentId 40)

我可以用光标做到这一点......但我认为存在一个简单的解决方法来做到这一点。 有什么想法吗?

测试数据:

DECLARE @table TABLE(
    instrumentId INT NOT NULL,
    priceListDate DATETIME NOT NULL,
    price DECIMAL NOT NULL 
)

INSERT INTO @table
(
    instrumentId,
    priceListDate,
    price
)
VALUES( 39, '2012-10-31 00:00:00.000',  150),
(39,'2012-11-01 00:00:00.000',  160),
(39,'2012-11-01 00:00:00.000',  200),
(40,'2012-10-31 00:00:00.000',  150),
(40,'2012-11-01 00:00:00.000',  140),
(40,'2012-11-01 00:00:00.000',  200),
(50,'2012-10-31 00:00:00.000',  150),
(50,'2012-11-01 00:00:00.000',  150),
(50,'2012-11-01 00:00:00.000',  150)

1 个答案:

答案 0 :(得分:3)

让我知道这是否正常。我猜你的表中不会有价格= -1,我认为这会给当前的解决方案带来问题。

WITH    CTE
      AS ( SELECT   RN = ROW_NUMBER() OVER ( ORDER BY instrumentId ) ,
                    *
           FROM     @table
         )
SELECT  CASE WHEN MIN(X.xPrice) = -1 THEN 0
             ELSE MAX(X.xPrice)
        END 'price' ,
        X.instrumentId
FROM    ( SELECT    CASE WHEN [Current Row].instrumentId = [Next Row].instrumentId
                         THEN CASE WHEN [Current Row].price > [Next Row].price
                                   THEN -1
                                   ELSE [Current Row].price
                              END
                         ELSE CASE WHEN [Previous Row].instrumentId = [Current Row].instrumentId
                                   THEN CASE WHEN [Previous Row].price <= [Current Row].price
                                             THEN [Current Row].price
                                             ELSE -1
                                        END
                                   ELSE [Current Row].price
                              END
                    END 'xPrice' ,
                    [Current Row].RN ,
                    [Current Row].instrumentId
          FROM      CTE [Current Row]
                    LEFT JOIN CTE [Previous Row] ON [Previous Row].RN = [Current Row].RN
                                                    - 1
                    LEFT JOIN CTE [Next Row] ON [Next Row].RN = [Current Row].RN
                                                + 1
        ) X
GROUP BY X.instrumentId

看起来有点复杂,但基本思路是确定当前打开的下一行和上一行,以便测试该行的价格列的值。