【问题标题】:Calculate salary by year按年计算工资
【发布时间】:2018-01-14 13:34:26
【问题描述】:

我想计算员工每年的工资。假设一名员工自 2016 年 7 月以来在公司工作了 1.5 年,那么我想分别显示 2 行的记录,例如 2016 年和 2017 年的工资。如果月薪是20000,那么对于18 months,结果应该是这样显示的。

EmpID  Year   MonthlySalary  YearlySalary  TotalSalary
1      2016   20000          120000        120000 (because was hired in jul)
1      2017   20000          240000        360000
2      2017   18000          216000        216000

我有一个查询,可以计算每月工资、年工资和总工资。我正在使用月数计算总工资。

CREATE TABLE EmployeeInfo (
EmpID Int,
FirstName Varchar(25),
LastName Varchar(25),
MonthlySalary Int,
DOJ Date);


INSERT INTO EmployeeInfo VALUES (1, 'Ahmad', 'Usman', '20000', '2016-06-01');
INSERT INTO EmployeeInfo VALUES (2, 'Erick', 'Ortiz', '18000', '2017-01-01');


SELECT [EmployeeName] = [EI].[FirstName] + ' ' + [EI].[LastName],
       [EI].[DOJ],
       [MonthlySalary] = [EI].MonthlySalary,
       [EXPERIENCE] = ( CONVERT(VARCHAR(2), Datediff(YEAR, [DOJ], Getdate())) ),
       [TotalSalary] = ( ( CONVERT(VARCHAR(2), Datediff(MONTH, [DOJ], Getdate())) ) * ( Isnull(NULL, [EI].MonthlySalary) ) )
FROM   [EmployeeInfo] [EI] 

【问题讨论】:

  • 发布预期结果
  • @Pரதீப் 预期输出在帖子的开头。
  • 你使用的是哪个版本的sql server?
  • 这需要计算到哪一年?
  • 我想计算所有年份。请阅读说明。如果该员工是 2016 年入职的,那么我想分别计算 2016 年的工资和 2017 年的工资。

标签: sql sql-server


【解决方案1】:

您需要一个日历表来执行此操作,我使用递归 cte 来生成日期。

;WITH cte
     AS (SELECT EmpID, FirstName, LastName, MonthlySalary, DOJ, cntr = 1, SalaryMonth = DOJ
         FROM   EmployeeInfo
         UNION ALL
         SELECT e.EmpID, e.FirstName, e.LastName, e.MonthlySalary, e.DOJ, cntr = cntr + 1, Dateadd(month, cntr, e.DOJ)
         FROM   cte c
                JOIN EmployeeInfo e
                  ON c.EmpID = e.EmpID
         WHERE  Dateadd(month, cntr, e.DOJ) < DATEADD(dd,-(DAY(Getdate())),Getdate()))
SELECT EmpID,
       [Year] = Year(SalaryMonth),
       MonthlySalary,
       YearlySalary = Sum(MonthlySalary),
       TotalSalary = Sum(Sum(MonthlySalary)) OVER(partition BY EmpID ORDER BY Year(SalaryMonth))
FROM   cte
GROUP  BY EmpID, Year(SalaryMonth), MonthlySalary 
OPTION (MAXRECURSION 0)

【讨论】:

  • 如果我必须添加另一列怎么办?我正在尝试将部门表和指定表与员工信息相关联,但它不允许我
  • 部门的列名是FullName,员工信息的部门代码为外键,部门表的dptid为PK
  • 如果员工的薪水在某个时候发生变化怎么办。我该如何处理?
  • @Doonie Darkoo 请提出一个包含相关细节的新问题
【解决方案2】:

尝试递归 CTE。像这样

 ;WITH CTE
AS
(
    SELECT
        EmpId,
        EmpYr = YEAR(DOJ),
        Month = 12-CASE WHEN MONTH(DOJ) = 1 THEN 0 ELSE MONTH(DOJ) END,
        MonthlySalary,
        YearlySalary = MonthlySalary*(12-CASE WHEN MONTH(DOJ) = 1 THEN 0 ELSE MONTH(DOJ) END),
        TotalSal = MonthlySalary*(12-CASE WHEN MONTH(DOJ) = 1 THEN 0 ELSE MONTH(DOJ) END)
        FROM EmployeeInfo

    UNION ALL

    SELECT
        EmpId,
        EmpYr = EmpYr+1,
        Month = 12,
        MonthlySalary,
        YearlySalary = MonthlySalary*
                                (
                                  CASE WHEN EmpYr = YEAR(GETDATE()) 
                                        THEN MONTH(GETDATE())
                                      ELSE 12 END
                                 ),
        TotalSal = TotalSal+(MonthlySalary*
                                (
                                  CASE WHEN EmpYr = YEAR(GETDATE()) 
                                        THEN MONTH(GETDATE())
                                      ELSE 12 END
                                 ))
        FROM CTE
            WHERE EmpYr < YEAR(GETDATE())
)
SELECT
  EmpId,
  EmpYr,
  MonthlySalary,
  YearlySalary,
  TotalSalary = TotalSal
  FROM CTE
    ORDER BY EmpId

我的结果

查看DEMO

【讨论】:

  • 我添加了当年的工资,但它也给了我今年的工资,这是不正确的,因为如果当年只有一个月,那么为什么要给全年工资?
  • @DoonieDarkoo 我已经更新了答案以及 SqlFiddle 中的演示。请立即查看
【解决方案3】:
with sy as (
      Select EmpId, year(DOJ) cyear, FirstName+' '+LastName AS EmployeeName, 
      avg(MonthlySalary) MonthlySalary, sum(MonthlySalary) YearlySalary, avg(MonthlySalary)*12 TotalSalary
     FROM EmployeeInfo
     group by year(DOJ),FirstName+' '+LastName, EmpID
    )
select sy1.EmpId, sy1.cyear, sy1.EmployeeName, sy1.MonthlySalary MonthlySalary, sy1.YearlySalary, sum(sy2.YearlySalary) TotalSalary from
sy sy1, sy sy2
where sy1.EmpId = sy2.EmpId and sy1.EmployeeName = sy2.EmployeeName and sy1.cyear >= sy2.cyear 
group by sy1.EmpId, sy1.cyear, sy1.EmployeeName, sy1.YearlySalary,sy1.MonthlySalary

(添加了 EmpId)

【讨论】:

    【解决方案4】:

    您可以制作一个简单的引用表,然后进行连接。

    注意:“Sum (....) OVER (....)”仅适用于 SQL Server 2012 或更高版本。

    WITH REF ( YY ) AS (
        SELECT 2017  --OR USE THE LATEST YEAR PREFERRED.
        UNION ALL
        SELECT  YY - 1
        FROM REF
        WHERE REF.YY > 1950 -- SET THE EARLIEST YEAR
    )
    SELECT 
        EI.EmpID,
        REF.YY AS [Year],
        EI.MonthlySalary,
        CASE WHEN REF.YY = YEAR(DOJ) THEN MonthlySalary*(13-MONTH(DOJ))
            ELSE MonthlySalary * 12 END AS YearlySalary,
        SUM (CASE WHEN REF.YY = YEAR(DOJ) THEN MonthlySalary*(13-MONTH(DOJ))
            ELSE MonthlySalary * 12 END ) OVER (PARTITION BY EMPID ORDER BY REF.YY) TotalSalary
        FROM [EmployeeInfo] [EI]
    JOIN
        REF
    ON
        YEAR(DOJ) <= YY
    ORDER BY 
        EI.EMPID, REF.YY
    ;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-24
      • 2019-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多