SQL Server / T-SQL:如何更新结果集的相等百分比?

时间:2010-05-10 17:02:07

标签: sql sql-server tsql

我需要一种方法来获取KeyID的结果集并将其尽可能平均分配,并根据KeyID为每个部门更新记录。换句话说,有

SELECT KeyID
FROM   TableA
WHERE (some criteria exists)

我想通过3个相等的KeyID更新TableA 3的不同方式。

UPDATE TableA
SET    FieldA = Value1
WHERE  KeyID IN (the first 1/3 of the SELECT resultset above)

UPDATE TableA
SET    FieldA = Value2
WHERE  KeyID IN (the second 1/3 of the SELECT resultset above)

UPDATE TableA
SET    FieldA = Value3
WHERE  KeyID IN (the third 1/3 of the SELECT resultset above)

或其他相似之处。感谢您的任何和所有回复。

6 个答案:

答案 0 :(得分:4)

With TiledItems As
    (
        Select KeyId
            , NTILE(3) OVER( ORDER BY ... ) As NTileNum
        From TableA
        Where ...
    )
Update TableA
Set FieldA = Case TI.NTileNum
                    When 1 Then Value1
                    When 2 Then Value2
                    When 3 Then Value3
                    End
From TableA As A
    Join TiledItems As TI
        On TI.KeyId = A.KeyId

答案 1 :(得分:2)

不幸的是,我没有时间敲定一个完整的解决方案,但其中一个要点是使用带有NTILE函数http://msdn.microsoft.com/en-us/library/ms175126.aspx的CTE分成3组,然后在UPDATE语句中加入到CTE中并针对NTILE组执行CASE语句,以确定是使用Value1,Value2还是Value3。

修改 请参阅Thomas's回答代码,看起来他有同样的想法!

答案 2 :(得分:1)

对于简单分发,创建随机排名并以3 ...

为模
UPDATE
    A
SET
    FieldA =
        CASE Ranking % 3
           WHEN 1 THEN B.Value1
           WHEN 2 THEN B.Value2
           WHEN 0 THEN B.Value3
        END
FROM
    TableA A
    inner join
    (SELECT
        ID,
        ROW_NUMBER() OVER (ORDER BY ID /*or something*/) AS Ranking,
        Value1, Value2, Value3
    FROM
        TableA
    ) B on A.ID = B.ID
where (some criteria exists)

您可以更改ROW_NUMBER()的ORDER BY,或使用NTILE并删除模数

答案 3 :(得分:1)

如果密钥均匀分布,则可以使用模数(%)运算符选择结果集的唯一三分之一。

update TableA set FieldA = Value1 where KeyID % 3 = 0;
update TableA set FieldA = Value2 where KeyID % 3 = 1;
update TableA set FieldA = Value3 where KeyID % 3 = 2;

答案 4 :(得分:0)

按字面解释你所说的内容,你可以对返回的行集中的行进行编号,然后根据行号选择不同的部分。

E.g。

UPDATE TableA
SET    FieldA = Value1
WHERE  KeyID IN (SELECT * FROM (SELECT <your rows>, ROW_NUMBER() (ORDER BY <anyRow>) AS RowNumber FROM <yourTable> ) base
WHERE RowNumber<Count(RowNumber)/3)

UPDATE TableA
SET    FieldA = Value1
WHERE  KeyID IN (SELECT * FROM (SELECT <your rows>, ROW_NUMBER() (ORDER BY <anyRow>) AS RowNumber FROM <yourTable> ) base
WHERE RowNumber<Count(RowNumber)*2/3 && RowNumber>=Count(RowNumber)/3)

UPDATE TableA
SET    FieldA = Value1
WHERE  KeyID IN (SELECT * FROM (SELECT <your rows>, ROW_NUMBER() (ORDER BY <anyRow>) AS RowNumber FROM <yourTable> ) base
WHERE owNumber>=Count(RowNumber)*2/3)

答案 5 :(得分:0)

WITH Query (OtherKeyID, PCT)
AS
(
SELECT  KeyID, (ROW_NUMBER() OVER (ORDER BY KeyID)) / foo.CNT AS PCT 
FROM    TableA 
JOIN    (SELECT CONVERT(float, COUNT(1)) AS CNT FROM TableA) foo ON 1 = 1 
WHERE   (criteria)
)

UPDATE TableA  
SET    FieldA = (CASE
    WHEN PCT < .3333 THEN Value1 
    WHEN PCT BETWEEN .3333 and .6666 THEN Value2
    WHEN PCT > .6666 THEN Value3 ELSE NULL END)
FROM   Query 
WHERE  KeyID = OtherKeyID AND PCT < .3333 

请注意,您可以将查询中的ORDER BY子句更改为任何有效的表达式,这样您就可以按任何条件定义“前三分之一”。