2016-12-27 51 views
1
CREATE TABLE #empInfo(emp_id INT, dept_id INT, salary INT) 
CREATE TABLE #empBonus(dep_id INT, emp_id INT, bonus INT) 

我有以上兩代表爲EmployeeBonus,在這裏我將分配獎金每年獎金錶中的員工,但例如我們要做到這一點,每年只要所以沒有給出年份列。按比例分配獎金分配使用設置表

INSERT INTO #empInfo VALUES 
(111, 100, 5000), 
(112, 100, 4000), 
(113, 100, 4000), 
(114, 100, 3500), 
(115, 100, 4500), 
(116, 100, 3000), 
(114, 200, 3500), 
(115, 200, 4500), 
(116, 200, 3000), 
(114, 300, 3500), 
(115, 300, 3500), 
(116, 300, 3500) 

INSERT INTO #empBonus VALUES 
(100, 111, 1000), 
(100, NULL, 4000), 
(100, 111, 500), 
(100, NULL, 4000), 
(100, 113, 700), 
(200, 114, 600), 
(200, NULL, 1600), 
(300, 116, 900) 

以上,如果empBonus表中定義的員工ID,然後在獎金分配應該爲員工,如果無效,這意味着獎金,其不是在empBonus列出,並會根據自己的工資獲得獎勵所有員工。

我們可以爲多名員工定義獎金,對於同一名員工可以是多個獎金,在這種情況下,我們必須總計獎金並相應地執行操作。同樣的情況是NULL。

例如,立足以下的公式,我在下面做計算在EXCEL,便於理解和SQL我與OUTER APPLY努力,但沒有得到什麼,我從單個查詢想要的嗎?

--Formula = bonus*salary/totSalary(of respective group or employee) 
DeptID EmpID TotBonus Salary  TotSalary Bonus 
100  111  1500  5000  5000  1500.00000000000 
100  112  8000  4000  15000  2133.33333333333 
100  113  700   4000  4000  700.00000000000 
100  114  8000  3500  15000  1866.66666666666 
100  115  8000  4500  15000  2400.00000000000 
100  116  8000  3000  15000  1600.00000000000 
200  114  600   3500  3500  600.00000000000 
200  115  1600  4500  7500  960.00000000000 
200  116  1600  3000  7500  640.00000000000 
300  114  0   3500  7000  0.00000000000 
300  115  0   3500  7000  0.00000000000 
300  116  900   3500  3500  900.00000000000 

任何幫助將不勝感激,謝謝提前:)

+0

你是怎麼'TotSalary'? – Wanderer

+0

爲'111'員工定義了獎金,因此'111'的總工資爲'5000',對於其他組合獎金則定義爲總薪水爲所有這些員工薪水的總和。即上例中的「19000」。我們也可以通過另一種方法。 – Susang

+0

您可以請您分享您在Excel中完成的獎金分配公式嗎? – Abhay

回答

1

這裏使用的一種方式FULL OUTER JOINSUM() OVER()窗口集合

;WITH cte 
    AS (SELECT ei.emp_id,ei.dept_id, eb.dep_id, 
       bonus = COALESCE(bonus, Max(CASE WHEN eb.emp_id IS NULL THEN bonus END) 
              OVER(partition BY COALESCE(ei.dept_id, eb.dep_id))), 
       salary = Cast(salary AS NUMERIC(22, 6)), 
       TotSalary= Iif(eb.emp_id IS NULL, Sum(CASE WHEN eb.emp_id IS NULL THEN salary END) 
                OVER(partition by ei.dept_id), salary) 
     FROM #empInfo ei 
       FULL OUTER JOIN (SELECT bonus= Sum(bonus), 
             dep_id, 
             emp_id 
           FROM #empBonus 
           GROUP BY dep_id, 
              emp_id) eb 
          ON ei.dept_id = eb.dep_id 
           AND eb.emp_id = ei.emp_id) 
SELECT emp_id, 
     bonus, 
     salary, 
     TotSalary, 
     (bonus * salary)/NULLIF(TotSalary, 0) 
FROM cte 
WHERE emp_id IS NOT NULL 

結果:

+--------+-------+-------------+-----------+--------------------+ 
| emp_id | bonus | salary | TotSalary | Bonus Distribution | 
+--------+-------+-------------+-----------+--------------------+ 
| 111 | 1500 | 5000.000000 |  5000 | 1500.00000000000 | 
| 112 | 8000 | 4000.000000 |  19000 | 1684.21052631578 | 
| 113 | 8000 | 4000.000000 |  19000 | 1684.21052631578 | 
| 114 | 8000 | 3500.000000 |  19000 | 1473.68421052631 | 
| 115 | 8000 | 4500.000000 |  19000 | 1894.73684210526 | 
| 116 | 8000 | 3000.000000 |  19000 | 1263.15789473684 | 
+--------+-------+-------------+-----------+--------------------+ 
+0

您的查詢已經過測試,並且對於我當前的場景+1確實有效,但正如我在'BONUS'中所說的,表中的記錄可以是多個或重複的,在這種情況下,我們必須'SUM'值並進行相應的分配。如果我添加(100,111,500), (100,NULL,4000),你應該更新它應該分配總計8000到所有應該分配1500到111. – Susang

+0

@Suraz - 更新.... –

+0

謝謝, @Prdp從各個方面都可以完美地工作,我會在經過幾次更多的測試後馬上回來:) – Susang

1

嗯,這對我來說是一個很好的挑戰。

首先,創建一個CTE是計算TotSalary柱:

;With cteTotalSalary as 
(
    -- select total salary for employees that are in the bonus table 
    SELECT e.emp_id, dept_id, Salary, Salary As TotSalary 
    FROM #empInfo e 
    INNER JOIN #empBonus b ON e.dept_id = b.dep_id AND e.emp_id = b.emp_id 

    UNION 

    -- select total salary for employees that are in NOT the bonus table 
    SELECT e.emp_id, dept_id, Salary, SUM(Salary) OVER(PARTITION BY dept_id) As TotSalary 
    FROM #empInfo e 
    WHERE EXISTS (
     SELECT 1 
     FROM #empBonus b 
     WHERE e.dept_id = b.dep_id 
     AND b.emp_id IS NULL 
    ) 
    AND NOT EXISTS 
    (
     SELECT 1 
     FROM #empBonus b 
     WHERE e.dept_id = b.dep_id 
     AND e.emp_id = b.emp_id 
    ) 
) 

然後,工會兩次查詢這個CTE得到兩種類型的獎金(員工獎金與部門獎金)

-- Get the bonus of the employess that exists in the empBonus table 
SELECT c.emp_id, dept_id, SUM(Bonus) OVER(PARTITION BY c.emp_id) as Bonus, Salary, TotSalary, CAST(SUM(CAST(Bonus as decimal)) OVER(PARTITION BY c.emp_id) as decimal) as [Bonus Distribution] 
FROM cteTotalSalary c 
INNER JOIN #empBonus b ON c.dept_id = b.dep_id AND c.emp_id = b.emp_id 

UNION 

-- Get the bonus of the employees that does not exists in the empBonus table 
SELECT c.emp_id, dept_id, SUM(Bonus) OVER(PARTITION BY c.emp_id), Salary, TotSalary, SUM(CAST(Bonus as decimal) * Salary/TotSalary) OVER(PARTITION BY c.emp_id) 
FROM cteTotalSalary c 
INNER JOIN #empBonus b ON c.dept_id = b.dep_id AND b.emp_id IS NULL 
AND NOT EXISTS (
     SELECT 1 
     FROM #empBonus b 
     WHERE c.dept_id = b.dep_id 
     AND c.emp_id = b.emp_id 
) 

結果:

emp_id dept_id Bonus Salary TotSalary Bonus Distribution 
111  100  1500 5000 5000  1500.000000000 
112  100  8000 4000 19000  1684.210526314 
113  100  8000 4000 19000  1684.210526314 
114  100  8000 3500 19000  1473.684210526 
115  100  8000 4500 19000  1894.736842104 
116  100  8000 3000 19000  1263.157894736 

你可以看到它在行動here

+0

它也滿足了我目前的要求(+1),但是我發現它有點冗長,我們可以解決上面在@Prdp答案中的註釋中提到的多值場景。 – Susang

+0

我看到Prdp已經更新了他的回答來解決這個問題,你是否還需要我的更新? –

+0

我的榮幸先生,這對每個人都有幫助。 – Susang