Tsql 将设备分成不均匀的百分比桶

Tsql 将设备分成不均匀的百分比桶,tsql,set,ssms,sql-server-2016,Tsql,Set,Ssms,Sql Server 2016,每天我都会收到一组介于5到2000之间的x行 我需要根据规则更新此集合中的列。我认为这个不完全有效的例子说明了这一点 /* 35% a 25% b 30% c 10% null */ WITH tally (vals, updateThis, bucket) AS ( SELECT DATEADD(DAY, - ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), GETDATE())

每天我都会收到一组介于5到2000之间的x行

我需要根据规则更新此集合中的列。我认为这个不完全有效的例子说明了这一点

/* 
    35% a
    25% b
    30% c
    10% null
*/

WITH tally
(vals, updateThis, bucket)
AS
(
    SELECT
         DATEADD(DAY, - ROW_NUMBER() OVER (ORDER BY (SELECT NULL)), GETDATE())
        , NULL
        , NTILE(100) OVER (ORDER BY (SELECT NULL))
    FROM
    (
        VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0)) AS a(n)
        CROSS JOIN (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0)) AS b(n)
        CROSS JOIN (VALUES (0), (0), (0), (0), (0), (0), (0), (0), (0)) AS c(n)
    )
--UPDATE
    --SET updateThis
, updated
AS
(
    SELECT
     t.vals
    , CASE
        WHEN t.bucket <= 35 THEN 'a'
        WHEN t.bucket > 35 AND t.bucket <=60 THEN 'b'
        WHEN t.bucket > 60 AND t.bucket <=90 THEN 'c'
        WHEN t.bucket > 60 AND t.bucket <=90 THEN 'NULL'
    END AS updated
    , t.bucket
    FROM tally t
)
SELECT 
    U.updated
    , COUNT(1) AS actual
FROM 
updated u
GROUP BY U.updated
此解决方案不精确,即使a+b+c占100%,也可能不会更新所有行。对于小于100行的集合,它也不起作用

我目前的工作方案是:

计算总行数 计算所需的实际行数CEILING@totalRows*每100人的比率 更新WHILE循环中的最终集,选择当前值和所需的行。
有没有更好的基于集合的解决方案可以帮助我摆脱循环?

不知道,如果我正确地理解了这一点

首先,这里似乎有一个相当明显的错误:

    WHEN t.bucket > 60 AND t.bucket <=90 THEN 'NULL'
函数NTILE将把你的集合分散成相当均匀的桶。检查我的输出,并找出在角落案例中的行为。我建议使用每行的计算百分比,如下所示:

符合 桶 像 选择 DATEADDDAY,-订单上的行号,选择NULL,GETDATE ,NTILE100超过订单,选择NULL 从…起 值0,0,0,0,0,0,0,0,0,0,0作为 交叉连接值0,0,0,0,0,0,0,0,0,0,0作为bn 交叉连接值0,0,0,0,0,0,0,0,0,0,0作为cn 挑选* 进入tmpBuckets 从理货; -我使用这个tmpBuckets表来更接近您的“我有一个表”场景

编号为 挑选* ,按VAL DESC/选择tmpBuckets/100.0中的计数*作为运行百分比的行数超额订购 来自tmpBuckets ,计算桶为 选择 t* 案例 当t.RunningPercentage 35、t.RunningPercentage 60和t.RunningPercentage 90时,则为“NULL” 以ShnugoMethod结束 案例 当t.bucket 35和t.RunningPercentage 60和t.RunningPercentage 90时,则为“NULL” 以ZikatoMethod结束 从编号t开始 选择cb* 来自ComputeBuckets cb 按cb.VAL DESC订购 去 升降台tmpBuckets;
我想您知道,如何使用这样的cte来更新源表。否则,请回答另一个问题:-

不知道,如果我理解正确

首先,这里似乎有一个相当明显的错误:

    WHEN t.bucket > 60 AND t.bucket <=90 THEN 'NULL'
函数NTILE将把你的集合分散成相当均匀的桶。检查我的输出,并找出在角落案例中的行为。我建议使用每行的计算百分比,如下所示:

符合 桶 像 选择 DATEADDDAY,-订单上的行号,选择NULL,GETDATE ,NTILE100超过订单,选择NULL 从…起 值0,0,0,0,0,0,0,0,0,0,0作为 交叉连接值0,0,0,0,0,0,0,0,0,0,0作为bn 交叉连接值0,0,0,0,0,0,0,0,0,0,0作为cn 挑选* 进入tmpBuckets 从理货; -我使用这个tmpBuckets表来更接近您的“我有一个表”场景

编号为 挑选* ,按VAL DESC/选择tmpBuckets/100.0中的计数*作为运行百分比的行数超额订购 来自tmpBuckets ,计算桶为 选择 t* 案例 当t.RunningPercentage 35、t.RunningPercentage 60和t.RunningPercentage 90时,则为“NULL” 以ShnugoMethod结束 案例 当t.bucket 35和t.RunningPercentage 60和t.RunningPercentage 90时,则为“NULL” 以ZikatoMethod结束 从编号t开始 选择cb* 来自ComputeBuckets cb 按cb.VAL DESC订购 去 升降台tmpBuckets;
我想您知道,如何使用这样的cte来更新源表。否则,请回答另一个问题:-

这真是……太美了!“我不知道为什么我没有想到这一点,我现在看到它似乎很简单。”齐卡托很高兴帮助你-这…真漂亮!“我不知道为什么我没有想到这一点,我现在看到它似乎很简单。”齐卡托很高兴帮助你-