You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于现有值将整数分配到列行(寻求集合式SQL方案)

集合式整数分配解决方案

要实现将指定整数分配到各行,使最终值尽可能接近(模拟每次给当前最小值加1的逻辑),可以通过排序+累计增量计算的集合式SQL完成,无需循环或游标,效率大幅提升。

核心思路

  1. 按原始值升序排序,优先给数值小的行分配更多增量,还原循环中每次选最小值加1的逻辑。
  2. 计算「填平」到某一行数值所需的累计增量:即把前面所有行的数值拉到当前行水平需要的总增量。
  3. 找到当前分配总量能覆盖的最大「填平」级别,计算剩余增量,再将剩余增量平均分配给前面的行(余数部分给前N行各加1)。

完整SQL实现

假设你的临时表为#Users,结构为UserIdMember INT, PreExistingAmount INT(对应问题中的Id和Bin),要分配的整数为@IntegerToDistribute:

DECLARE @IntegerToDistribute INT = 7; -- 可替换为20或其他值

WITH RankedUsers AS (
    SELECT 
        UserIdMember,
        PreExistingAmount,
        ROW_NUMBER() OVER (ORDER BY PreExistingAmount ASC) AS rn,
        COUNT(*) OVER () AS total_rows
    FROM #Users
),
-- 递归计算累计填平到当前行数值所需的总增量
RecursiveCumulative AS (
    SELECT
        UserIdMember,
        PreExistingAmount,
        rn,
        total_rows,
        CAST(0 AS BIGINT) AS cumulative_increment,
        PreExistingAmount AS current_level
    FROM RankedUsers
    WHERE rn = 1
    UNION ALL
    SELECT
        ru.UserIdMember,
        ru.PreExistingAmount,
        ru.rn,
        ru.total_rows,
        rc.cumulative_increment + (ru.PreExistingAmount - rc.current_level) * (ru.rn - 1),
        ru.PreExistingAmount
    FROM RankedUsers ru
    JOIN RecursiveCumulative rc ON ru.rn = rc.rn + 1
),
-- 找到当前分配量能覆盖的最大填平级别
Threshold AS (
    SELECT
        MAX(rn) AS max_rn,
        cumulative_increment,
        current_level
    FROM RecursiveCumulative
    WHERE cumulative_increment <= @IntegerToDistribute
),
-- 计算剩余待分配的增量
Remaining AS (
    SELECT
        @IntegerToDistribute - cumulative_increment AS remaining,
        max_rn,
        current_level
    FROM Threshold
)
-- 计算最终结果
SELECT
    ru.UserIdMember,
    ru.PreExistingAmount + 
    CASE
        -- 前max_rn行:先填平到current_level,再分配剩余增量
        WHEN ru.rn <= Remaining.max_rn THEN
            (Remaining.current_level - ru.PreExistingAmount) + 
            FLOOR(Remaining.remaining / Remaining.max_rn) +
            CASE WHEN ru.rn <= (Remaining.remaining % Remaining.max_rn) THEN 1 ELSE 0 END
        -- 超过max_rn的行:无需填平,仅在剩余增量有多余时分配
        ELSE 0
    END AS FinalAmount
FROM RankedUsers ru
CROSS JOIN Remaining
ORDER BY ru.UserIdMember;

例子验证

例子1:@IntegerToDistribute=7

原始数据:

(1, 3), (2, 12), (3, 6)

执行后结果:

(1, 8), (2, 12), (3, 8)

计算过程:

  • 排序后为(1,3),(3,6),(2,12)
  • 填平到6需要3个增量(3→6),剩余7-3=4个增量
  • 4个增量平均分给前2行,每行加2,最终3+3+2=8,6+0+2=8,12+0=12

例子2:@IntegerToDistribute=22(修正原例子总和矛盾)

若分配22,原始总和21+22=43,执行后结果:

(1, 15), (2, 14), (3, 14)

计算过程:

  • 填平到12需要15个增量(3→12需9,6→12需6),剩余22-15=7个增量
  • 7个增量分给3行:每行先加2(3×2=6),剩余1个给第1行,最终3+9+2+1=15,6+6+2=14,12+0+2=14

优势

  • 纯集合式操作,避免循环/游标带来的性能问题,即使@IntegerToDistribute极大也能快速计算
  • 完全符合代码规范,逻辑清晰可维护

内容的提问来源于stack exchange,提问作者vera.nygren

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 19:29:50