11

SQL Server 2008 R2 の場合

このような結果セットがあります ([価格] は数値であり、以下の NULL は NULL 値を表し、結果セットは product_id とタイムスタンプで並べ替えられていることに注意してください)

product timestamp          price 
------- ----------------   -----
   5678 2008-01-01 12:00   12.34
   5678 2008-01-01 12:01    NULL
   5678 2008-01-01 12:02    NULL
   5678 2008-01-01 12:03   23.45
   5678 2008-01-01 12:04    NULL

これを、直前の行から null 以外の値を (本質的に) コピーする結果セットに変換して、次のような結果セットを生成したいと考えています。

product timestamp          price  
------- ----------------   -----
   5678 2008-01-01 12:00   12.34
   5678 2008-01-01 12:01   12.34
   5678 2008-01-01 12:02   12.34
   5678 2008-01-01 12:03   23.45
   5678 2008-01-01 12:04   23.45

これを可能にする集計/ウィンドウ関数が見つかりません(これもSQL Server 2008 R2にのみ必要です)。

私はこれを行う分析集計関数を見つけたいと思っていました...

LAST_VALUE(price) OVER (PARTITION BY product_id ORDER BY timestamp)

しかし、ウィンドウで「累積的な最新のnull以外の値」を実行する方法が見つからないようです(ウィンドウをパーティション全体ではなく、前の行にバインドするため)

テーブル値のユーザー定義関数を作成する以外に、これを実現するビルトインはありますか?


アップデート:

どうやら、この機能は「デナリ」CTP で利用できますが、SQL Server 2008 R2 では利用できません。

LAST_VALUE http://msdn.microsoft.com/en-us/library/hh231517%28v=SQL.110%29.aspx

SQL Server 2008 で利用できると思っていました。Oracle で利用できます (少なくとも 10gR2 以降)。ローカル変数を使用して、MySQL 5.1 でも同様のことができます。

http://download.oracle.com/docs/cd/E14072_01/server.112/e10592/functions083.htm

4

3 に答える 3

13

次のことを試すことができます。

* 更新しました **

-- Test Data
DECLARE @YourTable TABLE(Product INT, Timestamp DATETIME, Price NUMERIC(16,4))

INSERT INTO @YourTable
SELECT 5678, '20080101 12:00:00', 12.34
UNION ALL
SELECT 5678, '20080101 12:01:00', NULL
UNION ALL
SELECT 5678, '20080101 12:02:00', NULL
UNION ALL
SELECT 5678, '20080101 12:03:00', 23.45
UNION ALL
SELECT 5678, '20080101 12:04:00', NULL

;WITH CTE AS
(
    SELECT *
    FROM @YourTable
)

-- Query
SELECT A.Product, A.Timestamp, ISNULL(A.Price,B.Price) Price
FROM CTE A
OUTER APPLY (   SELECT TOP 1 *
                FROM CTE 
                WHERE Product = A.Product AND Timestamp < A.Timestamp
                AND Price IS NOT NULL
                ORDER BY Product, Timestamp DESC) B

--Results
Product Timestamp   Price
5678    2008-01-01 12:00:00.000 12.3400
5678    2008-01-01 12:01:00.000 12.3400
5678    2008-01-01 12:02:00.000 12.3400
5678    2008-01-01 12:03:00.000 23.4500
5678    2008-01-01 12:04:00.000 23.4500
于 2011-08-12T19:12:58.207 に答える
4

これを試して:

;WITH SortedData AS
(
    SELECT
       ProductID, TimeStamp, Price,
       ROW_NUMBER() OVER(PARTITION BY ProductID ORDER BY TimeStamp DESC) AS 'RowNum'
    FROM dbo.YourTable
)
UPDATE SortedData
SET Price = (SELECT TOP 1 Price 
             FROM SortedData sd2
         WHERE sd2.RowNum > SortedData.RowNum 
           AND sd2.Price IS NOT NULL)
WHERE
    SortedData.Price IS NULL

基本的に、CTE はタイムスタンプ (降順) で並べ替えられたリストを作成します。NULL が見つかると、NOT NULL 価格を含む次の行が検出され、その値を使用して NULL 価格で行が更新されます。

于 2011-08-12T19:19:30.623 に答える