web-dev-qa-db-ja.com

識別子が現在の期間から削除されたときの値ウィンドウ関数の変化を計算します

ある期間から別の期間への値の変化を見つけるにはどうすればよいのか疑問に思っていましたが、私のシナリオでは、識別子が現在の期間から外れています。

これは、cteとselectの個別のIDを使用して実行できると思いますが、実装方法がわかりません。

以下のデモの日付

CREATE TABLE basic_pays (
    employee_id int,
    fiscal_year INT,
    salary DECIMAL(10 , 2 ),
    PRIMARY KEY (employee_id, fiscal_year)
);

INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(1,2017,24000);
INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(2,2017,17000);
INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(1,2018,25920);

SELECT 
    employee_id, 
    fiscal_year,
    salary,
    salary - LAG(salary) 
        OVER (PARTITION BY employee_id ORDER BY fiscal_year) salary_change
FROM
    basic_pays
GROUP BY 
    employee_id, fiscal_year, salary
ORDER BY fiscal_year, employee_id

DROP TABLE basic_pays

期待される出力は

| employee_id | fiscal_year | salary   | salary_change |
|-------------|-------------|----------|---------------|
| 1           | 2017        | 24000.00 | NULL          |
| 2           | 2017        | 17000.00 | NULL          |
| 1           | 2018        | 25920.00 | 1920.00       |
| 2           | 2018        | 0.00     | -17000.00     |
2
Glenn Sampson

このようにすることができますが、パフォーマンスに関しては、より大きなデータセットに悪影響を与える可能性があります。

;WITH CTE
AS
(
SELECT DISTINCT employee_id,a.fiscal_year
from basic_pays
CROSS APPLY
(
SELECT distinct fiscal_year 
from basic_pays
) as a)


SELECT   c.employee_id, 
    c.fiscal_year,
    CASE WHEN salary IS NULL then 0.00 else salary END as salary,
    CASE WHEN salary IS NULL then 0.00 else salary END - LAG(salary) 
        OVER (PARTITION BY c.employee_id ORDER BY c.fiscal_year) salary_change
FROM
    CTE c
LEFT JOIN basic_pays b
ON C.employee_id = b.employee_id
AND c.fiscal_year= b.fiscal_year;

結果

employee_id fiscal_year    salary       salary_change
1             2017        24000.00      NULL
1             2018        25920.00      1920.00
2             2017        17000.00      NULL
2             2018        NULL          -17000.00
3
Randi Vertongen

この目的のためにカレンダーテーブルを使用することをお勧めします。

テーブル値を使用してシミュレートしました。また、employee_id/fiscal yearによる行が1つしかない場合は、GROUPBY句を回避できます。

SELECT 
    emp_id, 
    fy,
    salary,
    COALESCE(salary,0) - LAG(salary) OVER (PARTITION BY emp_id ORDER BY fy) salary_change
FROM
    -- all combinations of year / employee_id
    (SELECT 
         emp_id, fy 
     FROM 
         (VALUES (2017),(2018)) as calendar(fy)
     CROSS JOIN
         -- it should be SELECT employee_id from employee's table
         (SELECT DISTINCT employee_id as emp_id FROM basic_pays) e) cal     LEFT JOIN
    basic_pays bp
    ON bp.employee_id = cal.emp_id
    AND bp.fiscal_year = cal.fy
ORDER BY 
    fy, emp_id
 emp_id | fy |給与| salary_change 
 -----:| ---:| :---- :------------ 
 1 | 2017年| 24000.00 | null
 2 | 2017年| 17000.00 | null
 1 | 2018 | 25920.00 | 1920.00 
 2 | 2018 | null| -17000.00 

db <>フィドル---(ここ

1
McNets