sql >> データベース >  >> Database Tools >> SSMS

同じデータのセットの日付範囲

    非リレーショナルソリューション

    他の答えはどれも正しいとは思いません。

    • GROUP BY 動作しません

    • ROW_NUMBER()の使用 データを物理的なレコードファイリングシステム構造に強制し、物理レコードとして処理します。莫大なパフォーマンスコストがかかります。もちろん、そのようなコードを書くためには、考える必要があります。 リレーショナル用語で考えるのではなく、RFSの観点から。

    • CTEの使用も同じです。データ、特に変更されないデータを反復処理します。わずかに異なる巨額の費用で。

    • カーソルは、さまざまな理由で間違いなく間違っています。 (a)カーソルにはコードが必要であり、ビューを要求しました。(b)カーソルはセット処理エンジンを放棄し、行ごとの処理に戻ります。繰り返しますが、必須ではありません。私のチームのいずれかの開発者がリレーショナルデータベース(つまり、レコードファイリングシステムではない)でカーソルまたは一時テーブルを使用している場合、それらを撮影します。

    リレーショナルソリューション

    1. あなたのデータ リレーショナル、論理、2つの与えられたデータ 必要なのは列だけです。

    2. 確かに、目的のレポートを取得するには、ビュー(派生リレーション)を作成する必要がありますが、これは純粋なSELECTで構成されており、処理(ファイルへの変換)とはまったく異なります。 、これは物理的であり、ファイルを処理します;または一時テーブル。または作業台;またはCTE;またはROW_Number();など)。

    3. 議題を持っている「理論家」の嘆きとは対照的に、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
    

    お楽しみください。

    コメントや質問など、お気軽にどうぞ。



    1. Magentoからすべての製品をエクスポートするには、データベースを最小化します

    2. PHP、MySQL検証の誤動作と検索が機能しませんか?

    3. データベース内の「http」を「https」に検索して置き換えます

    4. [実際の実行プランを含める]を使用してプログラムでクエリを実行し、インデックスの提案があるかどうかを確認する方法はありますか?