0

我有一个 3 列的表

+---------------+-------------+------ +
| 仪器 ID | 日期 | 价格 |
+---------------+-------------+------ +
| 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 |
+---------------+-------------+------ +

我需要接收下一个结果:

+--------------+------+
| 仪器 ID | 价格 |
+--------------+------+
| 39 | 200 |
| 40 | 0 |
| 50 | 150 |
+--------------+------+

规则:如果相同 InstrumentId 的价格在增长或等于 => 返回最后一个价格(这意味着每个下一个价格都大于或等于前一个价格。例如 Id 39:150 <= 160 <= 200 => 返回 200)如果有的话相同 InstrumentId 的价格低于先前 => 返回 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)
4

1 回答 1

3

让我知道这是否正常。我猜你的表中永远不会有 price = -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

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

于 2012-11-02T16:53:08.607 回答