非リレーショナルソリューション
他の答えはどれも正しいとは思いません。
-
GROUP BY
動作しません -
ROW_NUMBER()
の使用 データを物理的なレコードファイリングシステム構造に強制し、物理レコードとして処理します。莫大なパフォーマンスコストがかかります。もちろん、そのようなコードを書くためには、考える必要があります。 リレーショナル用語で考えるのではなく、RFSの観点から。 -
CTEの使用も同じです。データ、特に変更されないデータを反復処理します。わずかに異なる巨額の費用で。
-
カーソルは、さまざまな理由で間違いなく間違っています。 (a)カーソルにはコードが必要であり、ビューを要求しました。(b)カーソルはセット処理エンジンを放棄し、行ごとの処理に戻ります。繰り返しますが、必須ではありません。私のチームのいずれかの開発者がリレーショナルデータベース(つまり、レコードファイリングシステムではない)でカーソルまたは一時テーブルを使用している場合、それらを撮影します。
リレーショナルソリューション
-
あなたのデータ リレーショナル、論理、2つの与えられたデータ 必要なのは列だけです。
-
確かに、目的のレポートを取得するには、ビュー(派生リレーション)を作成する必要がありますが、これは純粋なSELECTで構成されており、処理(ファイルへの変換)とはまったく異なります。 、これは物理的であり、ファイルを処理します;または一時テーブル。または作業台;またはCTE;またはROW_Number();など)。
-
議題を持っている「理論家」の嘆きとは対照的に、SQLはリレーショナルデータを完全にうまく処理します。そして、あなたのデータはリレーショナルです。
したがって、リレーショナルの考え方、データのリレーショナルビュー、およびセット処理の考え方を維持します。リレーショナルデータベースのすべてのレポート要件は、単一のSELECTを使用して満たすことができます。 1970年以前のISAMファイル処理方法に戻る必要はありません。
主キー(リレーショナル行の一意性を与える列のセット)はDate,
であると想定します。 与えられたサンプルデータに基づくと、データ型はDATE.
です。
これを試してください:
CREATE VIEW MyTable_Base_V -- Foundation View
AS
SELECT Date,
Date_Next,
Price
FROM (
-- Derived Table: project rows with what we need
SELECT Date,
[Date_Next] = DATEADD( DD, 1, O.Date ),
Price,
[Price_Next] = (
SELECT Price -- NULL if not exists
FROM MyTable
WHERE Date = DATEADD( DD, 1, O.Date )
)
FROM MyTable MT
) AS X
WHERE Price != Price_Next -- exclude unchanging rows
GO
CREATE VIEW MyTable_V -- Requested View
AS
SELECT [Date_From] = (
-- Date of the previous row
SELECT MAX( Date_Next ) -- previous row
FROM MyTable_V
WHERE Date_Next < MT.Date
),
[Date_To] = Date, -- this row
Price
FROM MyTable_Base_V MT
GO
SELECT *
FROM MyTable_V
GO
メソッド、汎用
もちろん、これはメソッドであるため、一般的であり、From_
を決定するために使用できます。 およびTo_
任意のデータ範囲(ここでは、Date
範囲)、データの変更(ここでは、Price
の変更)に基づきます )。
ここで、Dates
連続しているため、Date_Next
の決定 簡単です:Date
をインクリメントします 1日までに。 PKが増加しているが、ではない場合 連続(例:DateTime
またはTimeStamp
または他のキー)、派生テーブルX
を変更します 宛先:
-- Derived Table: project rows with what we need
SELECT DateTime,
[DateTime_Next] = (
-- first row > this row
SELECT TOP 1
DateTime -- NULL if not exists
FROM MyTable
WHERE DateTime > MT.DateTime
),
Price,
[Price_Next] = (
-- first row > this row
SELECT TOP 1
Price -- NULL if not exists
FROM MyTable
WHERE DateTime > MT.DateTime
)
FROM MyTable MT
お楽しみください。
コメントや質問など、お気軽にどうぞ。