计算年初总计

时间:2017-12-30 08:30:10

标签: sql-server

我想生成一个薪资类型查询,其中薪资1(例如上个月)中的值应包含在薪资2(当前月份)年初至今总计中。

最好用一个例子来解释:

DECLARE @MyTable TABLE(ID INT IDENTITY, PayrollID INT, Description NVARCHAR(MAX), [Current Month] MONEY)

INSERT INTO @MyTable
VALUES  (1,'Basic Salary',100),
        (1,'Normal Over Time',50),
        (1,'Work on Saturday',150),
        (1,'Work on Sunday',200),

        (2,'Basic Salary',100)

SELECT * ,SUM([Current Month]) OVER (PARTITION BY  Description ORDER BY PayrollID) AS [Month to Date]
FROM @MyTable

当我运行以上内容时,我得到了

ID  EmployeeID  PayrollID   Description     Current Month   Month to Date
1      1           1        Basic Salary        100             100
2      1           1        Normal Over Time     50              50
3      1           1        Work on Saturday    150             150
4      1           1        Work on Sunday      200             200
5      1           2        Basic Salary        100             200

年初至今运行总计是每个描述含义基本工资类别有自己的运行总数,星期六和星期日等也是如此等。您会注意到,对于工资核算2中的基本工资,运行年份到 - 日期总计为200(即工资单1中的100,工资单2中的100)

我面临的挑战是,薪资1包含基本工资,星期六工作和星期日工作的数据,而工资核算2只有基本工资,因为员工周六没有工作,周日工资2(当月)

但是,在累计的“年初至今”列中,仍应选择工资核算1(上个月)的数据并将其包含在年初至今的总计中 - 像这样的东西:

ID  EmployeeID  PayrollID   Description     Current Month   Month to Date
1      1           1        Basic Salary         100            100
2      1           1        Normal Over Time      50             50
3      1           1        Work on Saturday     150            150
4      1           1        Work on Sunday       200            200
5      1           2        Basic Salary         100            200
2      1           1        Normal Over Time     NULL            50
3      1           1        Work on Saturday     NULL           150
4      1           1        Work on Sunday       NULL           200

虽然员工在本月的周六和周日没有工作(工资单2),但周六工作的运行(年初至今)总数应该是他/她在上个月工作的150(工资单) 1)。这应该适用于周日工作,当月的工资总额(工资2)应该是他/她在上个月工作的200(工资1)。

如何使用简单的Select语句而不编写复杂的过程?

修改

我按照以下方式清理了颂歌:

DECLARE @MyTable TABLE(ID INT IDENTITY, EmployeeID INT, PayrollID INT, Description NVARCHAR(MAX), [Current Month] MONEY)

INSERT INTO @MyTable
VALUES  (1,1,'Basic Salary',100),
        (1,1,'Normal Over Time',50),
        (1,1,'Work on Saturday',150),
        (1,1,'Work on Sunday',200),

        (1,2,'Basic Salary',100)
WITH pay_elements AS
(
    SELECT Description
    FROM @MyTable
    GROUP BY Description
)

,pay_slips AS
(
    SELECT EmployeeID, PayrollID
    FROM @MyTable
    GROUP BY EmployeeID, PayrollID
)
,pay_lines AS
(
    SELECT
        mt.ID
        ,PS.EmployeeID
        ,PS.PayrollID
        ,PE.Description
        ,ISNULL(mt.[Current Month], 0) AS [Current Month]

    FROM
        pay_slips AS ps

    OUTER APPLY
        pay_elements AS pe

    LEFT JOIN
        @MyTable AS mt
        ON (mt.EmployeeID = ps.EmployeeID)
        AND (mt.PayrollID = ps.PayrollID)
        AND (mt.Description = pe.Description)
)

SELECT * ,SUM([Current Month]) OVER (PARTITION BY EmployeeID, Description ORDER BY PayrollID) AS [Month to Date]
FROM pay_lines

我收到了这个错误:

Msg 319, Level 15, State 1, Line 10
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.
Msg 102, Level 15, State 1, Line 17
Incorrect syntax near ','.
Msg 102, Level 15, State 1, Line 23
Incorrect syntax near ','.

2 个答案:

答案 0 :(得分:0)

首先需要构建行标题的“结构”,然后将其连接到实际数据上。

例如:

WITH pay_elements AS
(
    SELECT Description
    FROM @MyTable
    GROUP BY Description
)
,pay_slips AS
(
    SELECT EmployeeID, PayrollID
    FROM @MyTable
    GROUP BY EmployeeID, PayrollID
)
,pay_lines AS
(
    SELECT
        mt.ID
        ,pay_slips.EmployeeID
        ,pay_slips.PayrollID
        ,pay_elements.Description
        ,ISNULL(mt.Current_Month, 0) AS Current_Month

    FROM
        pay_slips AS ps

    OUTER APPLY
        pay_elements AS pe

    LEFT JOIN
        @MyTable AS mt
        ON (mt.EmployeeID = ps.EmployeeID)
        AND (mt.PayrollID = ps.PayrollID)
        AND (mt.Description = pe.Description)
)

SELECT * ,SUM([Current Month]) OVER (PARTITION BY EmployeeID, Description ORDER BY PayrollID) AS [Month to Date]
FROM pay_lines

我们在这里做的是获取表格中不同类型的付费元素的列表。然后我们获得了迄今为止完成的员工和工资单列表,并手动强制每个工资单包含所有可能的薪酬元素的行。

构建该结构后,我们连接到基表以获取实际值(用零替换NULL,对于那些最初未包含在基表中的付费元素)。

然后我们就像你原来那样查询这个填充表。

注意,我已经动态写了这个,但没有检查过这段代码,所以请原谅任何小错误。

答案 1 :(得分:0)

我对你在描述中提到的年初至今的专栏感到困惑。我假设您的查询中可能包含[Month to Date]列。如果我错了,请纠正我。

我认为您要实现的目标是 - 工资单ID 2中不存在的描述,例如星期六的工作和星期日的工作也应该在结果集下方选择。

问题是:

  

NULL值的总和始终为NULL,因此如果[Current Month]值为NULL,则无法在[Month to Date]列中显示50,150,200

您可以针对每个工资核算ID设置固定类别:

  • 正常时间
  • 周六工作
  • 周日工作
  • 基本工资

<强>查询

DECLARE @MyTable TABLE(ID INT IDENTITY, PayrollID INT, Description NVARCHAR(MAX), [Current Month] MONEY)

INSERT INTO @MyTable
VALUES  (1,'Basic Salary',100),
        (1,'Normal Over Time',50),
        (1,'Work on Saturday',150),
        (1,'Work on Sunday',200),
        (2,'Basic Salary',100),
        (2,'Normal Over Time',0),
    (2,'Work on Saturday',0),
    (2,'Work on Sunday',0)


SELECT * ,SUM([Current Month]) OVER (PARTITION BY  Description ORDER BY PayrollID) AS [Month to Date]
FROM @MyTable order by ID,PayrollID