これを行うにはいくつかの方法があります。以下の例では、自己結合を使用しています。各レコードは、前月の同じ顧客のレコードに結合されます。
サンプルデータ
/* I've used a table variable to make sharing the example data
* easier. You could also use SQL Fiddle or Stack Data Explorer.
*/
DECLARE @Score TABLE
(
[Month] DATE,
AccountId NVARCHAR(50),
Score INT
)
;
-- Sample data taken from OP.
INSERT INTO @Score
(
[Month],
AccountId,
Score
)
VALUES
('2016-01-01', 'xxxxx1', 100),
('2016-01-01', 'xxxxx2', 200),
('2016-01-01', 'xxxxx3', 150),
('2016-02-01', 'xxxxx1', 120),
('2016-02-01', 'xxxxx2', 150),
('2016-02-01', 'xxxxx3', 180)
;
自己結合を使用すると、異なる行に表示される値を相互に比較できます。SQL Server 2012 以降には、LAG関数とLEAD関数があり、別のアプローチで同じことを実行できます。
/* Using a self join.
*/
SELECT
monthCurr.[Month],
monthCurr.AccountId,
monthCurr.Score AS CurrentScore,
monthLast.Score AS PreviousScore,
calc.Variance
FROM
@Score AS monthCurr
INNER JOIN @Score AS monthLast ON monthLast.AccountId = monthCurr.AccountId
AND monthLast.[Month] = DATEADD(MONTH, 1, monthCurr.[Month])
CROSS APPLY
(
/* Usign cross apply allows us to use Variance multiple times in the main query
* without rewritting the logic.
*/
SELECT
(monthCurr.Score - monthLast.Score) / CAST(monthLast.Score AS DECIMAL(18, 2)) * 100 AS Variance
) AS calc
WHERE
calc.Variance BETWEEN -20 AND -10
;
Score を整数として格納した場合は、CASTを使用して 10 進数に変換することを検討する必要があります。小数を使用した除算では、整数 (整数) よりも丸めが少なくなります。
CROSS APPLYを使用して分散を計算しました。これにより、ロジックを再入力することなく、SELECT 句と WHERE 句の両方で計算を再利用できます。