twgxzjk 2025-11-14 11:45 采纳率: 0%
浏览 6

求实现余额冲抵的SQL语句

问题描述:有以下一个SQLSERVER表记录员工调休在未来12个月每个月的剩余情况,出现负数的月份,需要优先用负数前面的月份抵扣掉负数,不够抵扣的再用负数后面的月份抵扣,没有发生抵扣的月份保持原值。

-- 创建测试表并插入示例数据
CREATE TABLE #EmployeeLeave (
    人员ID INT,
    月份 INT,
    本月过期加班 DECIMAL(10,2),
    次月过期加班 DECIMAL(10,2),
    第3月过期加班 DECIMAL(10,2),
    第4月过期加班 DECIMAL(10,2),
    第5月过期加班 DECIMAL(10,2),
    第6月过期加班 DECIMAL(10,2),
    第7月过期加班 DECIMAL(10,2),
    第8月过期加班 DECIMAL(10,2),
    第9月过期加班 DECIMAL(10,2),
    第10月过期加班 DECIMAL(10,2),
    第11月过期加班 DECIMAL(10,2),
    第12月过期加班 DECIMAL(10,2)
);

INSERT INTO #EmployeeLeave VALUES
(1, 202510, 4, 0, 0, 0, 0, 8.5, 0, 0, 0, 0, -7.5, 0);

想要的效果:
第6月过期加班=5.0,其他月份为0

  • 写回答

3条回答 默认 最新

  • 紫雾凌寒 新星创作者: 人工智能技术领域 2025-11-14 11:47
    关注

    让 “紫雾凌寒” 来帮你回答,本回答结合 DeepSeek

    如果还有问题,请评论或点击头像私信,如果有帮助到您, 请关注、采纳、点赞

    1. 关键点分析:
      - 要处理未来12个月每个月调休余额,且负数月份需按特定规则用前面和后面月份抵扣。
      - 需要遍历每个月的数据,根据余额正负情况进行相应计算和更新。
    2. 解决方案:
      - 可以使用循环来处理每个月的数据。以下是一个示例代码:
    -- 创建测试表
    CREATE TABLE EmployeeRest (
        MonthIndex INT,
        RestBalance DECIMAL(10, 2)
    );
    
    -- 插入测试数据
    INSERT INTO EmployeeRest (MonthIndex, RestBalance)
    VALUES (1, 10.0), (2, -5.0), (3, 20.0), (4, -15.0);
    
    -- 循环处理余额冲抵
    DECLARE @MonthIndex INT = 1;
    WHILE @MonthIndex <= 12
    BEGIN
        DECLARE @CurrentBalance DECIMAL(10, 2);
        SELECT @CurrentBalance = RestBalance
        FROM EmployeeRest
        WHERE MonthIndex = @MonthIndex;
    
        IF @CurrentBalance < 0
        BEGIN
            DECLARE @PrevMonthIndex INT = @MonthIndex - 1;
            WHILE @PrevMonthIndex > 0 AND @CurrentBalance < 0
            BEGIN
                DECLARE @PrevBalance DECIMAL(10, 2);
                SELECT @PrevBalance = RestBalance
                FROM EmployeeRest
                WHERE MonthIndex = @PrevMonthIndex;
    
                IF @PrevBalance > 0
                BEGIN
                    DECLARE @Diff DECIMAL(10, 2);
                    SET @Diff = CASE WHEN @PrevBalance + @CurrentBalance > 0
                                     THEN -@CurrentBalance
                                     ELSE @PrevBalance
                                     END;
                    UPDATE EmployeeRest
                    SET RestBalance = RestBalance - @Diff
                    WHERE MonthIndex = @PrevMonthIndex;
                    SET @CurrentBalance = @CurrentBalance + @Diff;
                END
                SET @PrevMonthIndex = @PrevMonthIndex - 1;
            END;
    
            DECLARE @NextMonthIndex INT = @MonthIndex + 1;
            WHILE @NextMonthIndex <= 12 AND @CurrentBalance < 0
            BEGIN
                DECLARE @NextBalance DECIMAL(10, 2);
                SELECT @NextBalance = RestBalance
                FROM EmployeeRest
                WHERE MonthIndex = @NextMonthIndex;
    
                IF @NextBalance > 0
                BEGIN
                    DECLARE @Diff DECIMAL(10, 2);
                    SET @Diff = CASE WHEN @NextBalance + @CurrentBalance > 0
                                     THEN -@CurrentBalance
                                     ELSE @NextBalance
                                     END;
                    UPDATE EmployeeRest
                    SET RestBalance = RestBalance - @Diff
                    WHERE MonthIndex = @NextMonthIndex;
                    SET @CurrentBalance = @CurrentBalance + @Diff;
                END
                SET @NextMonthIndex = @NextMonthIndex + 1;
            END;
        END
        SET @MonthIndex = @MonthIndex + 1;
    END;
    
    -- 查看结果
    SELECT * FROM EmployeeRest;
    
    1. 多种解决方案及优缺点:
      - 优点
      • 上述代码利用循环可以精确地按照规则处理每个月的余额冲抵情况,逻辑清晰。
      • 缺点
      • 代码相对复杂,嵌套的循环和条件判断较多,维护起来可能有一定难度。
      • 性能方面,对于大数据量的表,循环操作可能会导致性能问题。可以考虑使用窗口函数优化,但窗口函数在SQL Server中实现类似逻辑相对复杂一些。
    2. 总结:
      - 通过上述代码,实现了对员工调休余额按规则进行冲抵的功能。先循环遍历每个月,对于负数余额月份,优先用前面月份抵扣,不够再用后面月份抵扣,最后输出冲抵后的结果。代码逻辑较为复杂,在实际应用中可根据具体需求和数据量进行优化。

    希望以上解答对您有所帮助。如果您有任何疑问,欢迎在评论区提出。

    评论

报告相同问题?

问题事件

  • 创建了问题 11月14日