sql >> データベース >  >> RDS >> Sqlserver

SQLServerでOVER句とPARTITIONBY句を使用して現在の合計を計算する

    数量の現在の合計を計算する必要があるシナリオに出くわすことがよくあります。

    累計とは、特定の列の次のセルに先行する列のすべてのセルの値の合計を指します。

    これを明確にするための例を見てみましょう。

    ご覧のとおり、RunningAgeTotal列の3行目には、StudentAge列の1行から3行のすべての値の合計、つまり14 + 12 + 13=39が含まれています。

    同様に、RunningAgeTotal列の4行の値は49です。これは、StudentAge列の1行から4行の値の合計です。

    SQL Serverでは、OVER句を使用して現在の合計を計算できます。

    以下の例を参考にして、これを使用する方法を見てみましょう。

    SQLの現在の合計を計算する簡単な例

    累計を計算するクエリを実際に作成する前に、ダミーデータを作成しましょう。

    まず、次のスクリプトを実行します。

    CREATE DATABASE School
    GO
    
    USE School
    GO
    
    CREATE TABLE Students
    (
    	Id INT PRIMARY KEY IDENTITY,
    	StudentName VARCHAR (50),
    	StudentGender VARCHAR (50),
    	StudentAge INT
    )
    GO
    
    INSERT INTO Students VALUES ('Sally', 'Female', 14 )
    INSERT INTO Students VALUES ('Edward', 'Male', 12 )
    INSERT INTO Students VALUES ('Jon', 'Male', 13 )
    INSERT INTO Students VALUES ('Liana', 'Female', 10 )
    INSERT INTO Students VALUES ('Ben', 'Male', 11 )
    INSERT INTO Students VALUES ('Elice', 'Female', 12 )
    INSERT INTO Students VALUES ('Nick', 'Male', 9 )
    INSERT INTO Students VALUES ('Josh', 'Male', 12 )
    INSERT INTO Students VALUES ('Liza', 'Female', 10 )
    INSERT INTO Students VALUES ('Wick', 'Male', 15 )

    このスクリプトは、Schoolデータベース内にStudentsテーブルを作成します。テーブルには、Id、StudentName、StudentGender、Studentの4つの列があります。 INSERTステートメントは、データベースに10個のダミーレコードを追加します。

    SQLの現在の合計を計算するには、OVER句を使用して、現在の合計を計算する列を追加する必要があります。次のスクリプトは、StudentAge列の値の現在の合計を計算し、その結果をRunningAgeTotal列に追加します。

    USE School
    SELECT Id, StudentName, StudentGender, StudentAge,
    SUM (StudentAge) OVER (ORDER BY Id) AS RunningAgeTotal
    FROM Students

    上記のスクリプトでは、SELECTステートメントは、StudentName、StudentGender、およびStudentAge列を、現在の合計列、つまりRunningAgeTotalとともに取得します。 SUM Aggregate関数は、StudentAge列に値を加算し、OVER句は、Id列で順序付けられた現在の合計の形式で加算を実行する必要があることを決定します。上記のスクリプトの出力は次のとおりです。

    SQL移動平均の計算

    前のセクションのスクリプトを変更して、Studentsテーブルのすべての学生の移動平均年齢を計算できます。これを行うには、次のスクリプトを実行します。

    USE School
    SELECT Id, StudentName, StudentGender, StudentAge,
    SUM (StudentAge) OVER (ORDER BY Id) AS RunningAgeTotal,
    AVG (StudentAge) OVER (ORDER BY Id) AS RunningAgeAverage
    FROM Students

    ご覧のとおり、AVG集計関数を使用して、StudentAge列のすべての学生の平均年齢を計算します。上記のスクリプトの出力は次のようになります:

    RunningAgeAverage列の3行目を見てください。 StudentAge列の1〜3行の値の平均、つまり(14 + 12 + 13)/ 3=13が含まれます。

    現在の合計を列の値で分割する

    特定の列の値でデータを分割することにより、現在の合計を計算することもできます。たとえば、性別で分割された、学生の年齢のSQL累計を計算できます。これを行うには、OVER句とともにPARTITIONBYステートメントを使用する必要があります。

    次の例を見てください:

    USE School
    SELECT Id, StudentName, StudentGender, StudentAge,
    SUM (StudentAge) OVER (PARTITION BY StudentGender ORDER BY Id) AS RunningAgeTotal
    FROM Students

    すべてのレコードの現在の合計を計算することと、性別ごとに現在の合計を計算することの唯一の違いは、OVER句の後の括弧内にPARTITIONBYStudentGender句を使用することです。上記のスクリプトは、StudentAge列の値の現在の合計を、StudentGender列の値で分割して計算します。出力は次のようになります。

    次に、RunningAgeTotal列の最初の4つの値を見てください(赤い長方形で強調表示されています)。これらの値は、女子学生の累計です。同様に、最後の6行(緑色の長方形で強調表示されている)には、Studentsテーブルの男子生徒の年齢の現在の合計が含まれています。

    列に重複する列がある場合のOVERの問題

    現在の合計を計算するために、重複する値を持つ列がOVER句で使用される場合に問題が発生します。 StudentAge列を見てください。 Elice、Edward、Joshはすべて同じ年齢、つまり12です。同様に、LianaとLizaもStudentAge列で同じ値、つまり10を持っています。

    OVER句の後にある括弧内にStudentAge列を指定して現在の合計を計算しようとすると、奇妙な結果が表示されます。このクエリを実行してみましょう:

    USE School
    SELECT Id, StudentName, StudentGender, StudentAge,
    SUM (StudentAge) OVER (ORDER BY StudentAge) AS RunningAgeTotal
    FROM Students

    上記のクエリの出力は次のとおりです。

    RunningAgeTotal列の2行目の値は29です。ただし、StudentAge列の1行と2行にはそれぞれ9行と10行が含まれているため、19にする必要があります。この場合、StudentAge列の2行と3行の両方に重複した値、つまり10が含まれているため、RunningAgeTotal列の2行の値は、9、10、および10を加算して計算されます。 RunningAgeTotal列では、2行目の値である29が使用されます。

    同様に、RunningAgeTotal列の5行を見ると、値は76です。実際には40 + 12 =52である必要があります。ただし、StudentAge列の5、6、および7行には重複する値、つまり12があります。積算合計は、40 + 12 + 12 + 12 =76を加算して計算されます。StudentAge列の行6と7には重複する値が行として含まれているため、この積算合計は、RunningAgeTotal列の行6と7に使用されています。 5.

    この状況を回避するには、OVER句とともに重複する値を持つ列の使用を停止する必要があります。主キー列には一意の値しか含まれていないため、OVER句で使用するのに常に適しています。

    また読む:

    OVER関数とPARTITIONBY関数を使用したデータのグループ化

    OVERとPARTITIONBYの使用に関するレッスン


    1. エンベロープを取得します。つまり、重複する期間

    2. SQL-複数の類似クエリを組み合わせる

    3. convert_tzはnullを返します

    4. MariaDBでのMAKE_SET()のしくみ