SQL Server确保计算列不会变为负数

时间:2019-02-26 14:20:37

标签: sql-server

如果我有以下查询来计算雇员的病假余额

ALTER TABLE [dbo].[Employee]
ADD [SickLeaveEntitlementRemaining]  AS (case 

                when getdate()>=datefromparts(datepart(year,[StartDate]),datepart(month,[StartDate]),datepart(day,[StartDate])) AND getdate()<=dateadd(month,(6),datefromparts(datepart(year,[StartDate]),datepart(month,[StartDate]),datepart(day,[StartDate]))) then (0)-[SickLeaveTaken] 
                when getdate()>=dateadd(month,(6),datefromparts(datepart(year,[StartDate]),datepart(month,[StartDate]),datepart(day,[StartDate]))) AND getdate()<=dateadd(year,(1),datefromparts(datepart(year,[StartDate]),datepart(month,[StartDate]),datepart(day,[StartDate]))) then (8)-[SickLeaveTaken] 
                when getdate()>=dateadd(year,(1),datefromparts(datepart(year,[StartDate]),datepart(month,[StartDate]),datepart(day,[StartDate]))) AND getdate()<=dateadd(year,(3),datefromparts(datepart(year,[StartDate]),datepart(month,[StartDate]),datepart(day,[StartDate]))) then (24)-[SickLeaveTaken] 
                when getdate()>=dateadd(year,(3),datefromparts(datepart(year,[StartDate]),datepart(month,[StartDate]),datepart(day,[StartDate]))) AND getdate()<=dateadd(year,(1000),datefromparts(datepart(year,[StartDate]),datepart(month,[StartDate]),datepart(day,[StartDate]))) then (40)-[SickLeaveTaken]  end)

我如何确保该值永远不会变为负值,因为有时sickLeaveTaken会大于SickLeaveEntitlementRemaining

2 个答案:

答案 0 :(得分:1)

如果您希望小于0的值等于0,那么我会这样做:

ALTER TABLE [dbo].[Employee]
ADD [SickLeaveEntitlementRemaining] AS (CASE
                                             WHEN GETDATE() >= CONVERT(date, Startdate)
                                              AND GETDATE() <= DATEADD(MONTH, (6), CONVERT(date, Startdate)) THEN IIF((0) - [SickLeaveTaken] < 0, 0, (0) - [SickLeaveTaken])
                                             WHEN GETDATE() >= DATEADD(MONTH, (6), CONVERT(date, Startdate))
                                              AND GETDATE() <= DATEADD(YEAR, (1), CONVERT(date, Startdate)) THEN IIF((8) - [SickLeaveTaken] < 0, 0, (8) - [SickLeaveTaken])
                                             WHEN GETDATE() >= DATEADD(YEAR, (1), CONVERT(date, Startdate))
                                              AND GETDATE() <= DATEADD(YEAR, (3), CONVERT(date, Startdate)) THEN IIF((24) - [SickLeaveTaken] < 0, 0, (24) - [SickLeaveTaken])
                                             WHEN GETDATE() >= DATEADD(YEAR, (3), CONVERT(date, Startdate))
                                              AND GETDATE() <= DATEADD(YEAR, (1000), CONVERT(date, Startdate)) THEN IIF((40) - [SickLeaveTaken] < 0, 0, (40) - [SickLeaveTaken])
                                        END);

请注意,正如肖恩(Sean)所提到的,我也将庞大的DATEFROMPARTS表达式简化为CONVERT;使其更具可读性。

但是,就我个人而言,这不是一个好主意。如果某人的休假多于应有的休假时间,则应注意。这就是OP所要求的,但是,有“更好” 解决方案。尤其是如果您要停止请假的人多于他们应得的假期。

答案 1 :(得分:1)

您的规则可以通过这种方式简化

ALTER TABLE [dbo].[Employee]
    ADD [SickLeaveEntitlementRemaining]  AS ( 
        CASE 
            WHEN DATEDIFF(Year, StartDate, GETDATE()) >= 3 THEN IIF((40) - [SickLeaveTaken] < 0, 0, (40) - [SickLeaveTaken])
            WHEN DATEDIFF(Year, StartDate, GETDATE()) >= 1 THEN IIF((24) - [SickLeaveTaken] < 0, 0, (24) - [SickLeaveTaken])
            WHEN DATEDIFF(Month, StartDate, GETDATE()) >= 6 THEN IIF((8) - [SickLeaveTaken] < 0, 0, (8) - [SickLeaveTaken])
            ELSE 0 
        END
    )