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

SQLServerでの共通テーブル式の紹介

    Common Table Expressions(略してCTE)は、INSERT、SELECT、UPDATE、またはDELETEステートメント内で参照できるレコードの一時的なセットを作成するための単なる手法です。

    一般的なテーブル式は、MicrosoftによってSQL Server 2005で導入されました。それらの有効期間はクエリの実行時間と等しいため、データベースメモリにオブジェクトとして保存されません。クエリが完了するとすぐに、データベースメモリから削除されます。 CTEはクエリで何度でも参照でき、自己参照することもできます。

    学生テーブルを使用してデータベースを作成し、その中にダミーの学生レコードを挿入してみましょう。このデータベースを使用して、CTEクエリを記述します。いつものように、新しいコードを試す前に、十分にバックアップされていることを確認してください。よくわからない場合は、SQLバックアップに関するこの記事を参照してください。

    サーバーで次のクエリを実行します。

    CREATE DATABASE schooldb
    
    CREATE TABLE student
    (
        id INT PRIMARY KEY,
        name VARCHAR(50) NOT NULL,
        gender VARCHAR(50) NOT NULL,
        DOB datetime NOT NULL,
        total_score INT NOT NULL,
        
     )
    
    INSERT INTO student
    
    VALUES (1, 'Jolly', 'Female', '12-JUN-1989', 500), 
    (2, 'Jon', 'Male', '02-FEB-1974', 545), 
    (3, 'Sara', 'Female', '07-MAR-1988', 600), 
    (4, 'Laura', 'Female', '22-DEC-1981', 400), 
    (5, 'Alan', 'Male', '29-JUL-1993', 500), 
    (6, 'Kate', 'Female', '03-JAN-1985', 500), 
    (7, 'Joseph', 'Male', '09-APR-1982', 643), 
    (8, 'Mice', 'Male', '16-AUG-1974', 543), 
    (9, 'Wise', 'Male', '11-NOV-1987', 499), 
    (10, 'Elis', 'Female', '28-OCT-1990', 400);
    

    それでは、非常に単純な共通テーブル式を作成しましょう。このCTEには、1985年1月1日より前に生まれたすべての学生の記録が含まれます。次のスクリプトを参照してください。

    USE schooldb;
    
    WITH OldStudents AS
    (
    SELECT * FROM student
    WHERE DOB < '1985-01-01'
    )
    

    CTEを作成するには、「WITH」キーワードで始まり、その後にCTEの名前と「AS」キーワードが続く必要があります。

    次に、括弧内に、CTEが一時的に保存するレコードを返すクエリを作成する必要があります。上記のスクリプトでは、「OldStudents」という名前のCTEを作成しました。

    ただし、上記のクエリを実行しようとすると、エラーが発生することに注意してください。これは、CTEを作成したら、すぐに使用する必要があるためです。

    新しく作成した「OldStudents」CTEからすべてのレコードを選択しましょう。サーバーで次のスクリプトを試してください。

    USE schooldb;
    
    WITH OldStudents AS
    (
    	SELECT * FROM student
    	WHERE DOB < '1985-01-01'
    
    )
    
    SELECT * FROM OldStudents
    

    上記のスクリプトは、次のレコードのセットを取得します。

    CTEによる集計の計算

    テーブルと同様に、CTEで集計関数を実行できます。 CTEの別の例を見てみましょう。

    USE schooldb;
    
    WITH SumofScores AS
    (
    	SELECT 
    		gender, SUM(total_score) as SumScore
    	FROM student
    	GROUP BY gender
    )
    
    SELECT AVG (SumScore)
    FROM SumofScores
    

    上記の例では、SumofScoresという名前のCTEを作成しました。このCTEには、studentテーブルのtotal_score列に格納されている値の合計が含まれます。結果は性別の列でグループ化されます。 CTEによって保存されたデータは、メモリに次のように表示されます。

    次に、CTEの「SumScore」列でAVG関数を実行しました。スクリプトの最終結果は、2400と2730の平均、つまり2565になります。

    これは前の例よりも少し複雑ですが、CTEの概念をより明確に示しています。

    CTEでの列のラベル付け

    前の例では、CTEの2番目の列にエイリアスを追加しました。名前を「SumScore」に変更しました。これは、CTEで列にラベルを付ける1つの方法であり、テーブルの列エイリアスに似ています。

    ただし、CTEで列名を定義する別の方法があります。次のクエリを見てください。

    USE schooldb;
    
    WITH SumofScores(Gender, SumScore) AS
    (
    	SELECT 
    		gender, SUM(total_score)
    	FROM student
    	GROUP BY gender
    )
    
    SELECT AVG (SumScore)
    From SumofScores
    

    このスクリプトでは、CTE名の後の括弧内に「SumofScores」CTEの列名を追加しました。各列名はコンマで区切られます。

    CTEの後のSELECTステートメントを見ると、CTE名の後の括弧内に作成した「SumScore」列を参照していることがわかります。

    複数のCTEの作成

    これまでのすべての例では、わかりやすくするために1つの共通テーブル式のみを使用しています。 CTEのリストを同時に作成し、それらすべてを組み合わせて最終結果セットで使用できます。

    これは、例を使用して最もよく説明されます。以下のスクリプトをご覧ください。

    ここでは、2つのCTEを作成します。最初のCTEには、1985年1月1日より前に生まれた学生のすべての記録が保存されます。2番目のCTEには、1985年1月1日以降に生まれた学生のすべての記録が含まれます。

    その後、selectステートメントを使用して、両方のCTEからすべてのレコードを取得します。取得されたレコードは、UNIONステートメントを使用してマージされます。最後に、マージされたレコードは、生年月日の昇順で並べ替えられます。

    USE schooldb;
    
    WITH OldStudents AS
    (
    	SELECT * FROM student
    	WHERE DOB < '1985-01-01'
    
    ),
    
    YoungStudents AS
    (
    	SELECT * FROM student
    	WHERE DOB >= '1985-01-01'
    
    )
    
    (SELECT * FROM OldStudents
    UNION
    SELECT * FROM YoungStudents)
    
    ORDER BY DOB
    

    上記のSQLクエリでは、「OldStudents」と「YoungStudents」の2つのCTEを作成しました。すべてのCTEで「WITH」キーワードを使用する必要はないことを言及する価値があります。スクリプトの最初のCTEの前にのみ使用する必要があります。その後は、カンマで区切って任意の数のCTEを作成できます。

    上記のスクリプトは、次の結果を取得します。


    1. 2番目に高い給料の従業員を見つける方法は?

    2. どちらの時系列データベースが優れているか:TimescaleDBとInfluxDB

    3. PostgreSQLで月の最後の日を取得する

    4. SQL、Postgres OID、それらは何であり、なぜそれらは有用ですか?