LoginSignup
1
0

More than 1 year has passed since last update.

SQLのSUM関数内で(a - b)とさせたときの挙動

Posted at

SQL実践入門を読んでいて、挙動があまりイメージできなかったため調べたことを記載します。

内容はSQL実践入門を参考にさせていただいています。
サンプルコードはこちらで公開されています。

最初に結論

SUM関数内に複数列からなる式を入れると、各行の式で得られた結果を合計しているようでした。

以降で実際に試してみます

実行環境

  • Windows10 Home
  • Microsoft SQL Server 2019

テーブル作成

サンプルテーブルを作成します。

CREATE TABLE PriceByAge
(product_id VARCHAR(32) NOT NULL,
 low_age    INTEGER NOT NULL,
 high_age   INTEGER NOT NULL,
 price      INTEGER NOT NULL,
 PRIMARY KEY (product_id, low_age),
   CHECK (low_age < high_age));

データを作成します。

INSERT INTO PriceByAge VALUES('製品1',  0  ,  50  ,  2000);
INSERT INTO PriceByAge VALUES('製品1',  51 ,  100 ,  3000);
INSERT INTO PriceByAge VALUES('製品2',  0  ,  100 ,  4200);
INSERT INTO PriceByAge VALUES('製品3',  0  ,  20  ,  500);
INSERT INTO PriceByAge VALUES('製品3',  31 ,  70  ,  800);
INSERT INTO PriceByAge VALUES('製品3',  71 ,  100 ,  1000);
INSERT INTO PriceByAge VALUES('製品4',  0  ,  99  ,  8900);

SUM(a - b)を実行してみる

以下のコードでは、low_age ~ high_ageの値が0 ~ 100の連続になっている製品を取得しています。

SELECT product_id
  FROM PriceByAge
 GROUP BY product_id
HAVING SUM(high_age - low_age + 1) = 101;

※0から100までなので、値の数は101個あります

実行した結果はこちらです。
image.png (1.6 kB)

何が疑問だったのか

SUM関数内で計算式を渡したときは、どういう順序で計算されているんだろう?
ということでした。

サンプルコードを元に試してみる

改めてテーブルの全行を確認

SELECT * FROM PriceByAge;

実行結果
image.png (3.5 kB)

各行ごと計算結果と製品ごとの合計値を両方出してみる

SELECT product_id,low_age,high_age,(high_age - low_age + 1) AS 行の計算結果,
  SUM(high_age - low_age + 1)OVER( PARTITION BY PRODUCT_ID) AS SUM関数の結果
FROM PriceByAge
;

実行結果
image.png (4.5 kB)

実行結果から理解できたこと

それぞれの実行結果を見ると以下の計算順序になっていることがわかります。

  1. 各行の(high_age - low_age + 1)が計算されている

  2. 括弧内の計算の後に、GROUP BY product_idによる集約が行われる

  3. product_idごとにSUM関数による合計値の計算が行われる

感想

実際に調べてみると普通の四則演算と同じだなという感じで、
むしろなんで疑問に思ったのか不思議なレベルでした。
でも実際に動かしてみて腑に落ちたので良かったです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0