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 に答える