SQL Server / T-SQL: как обновить равные проценты в наборе результатов? - PullRequest
2 голосов
/ 10 мая 2010

Мне нужен способ взять набор результатов KeyID, разделить его как можно более равномерно и обновить записи по-разному для каждого подразделения на основе KeyID. Другими словами, есть

SELECT KeyID
FROM   TableA
WHERE (some criteria exists)

Я хочу обновить TableA 3 различными способами, используя 3 равные части KeyID.

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 ]

4 голосов
/ 10 мая 2010
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
2 голосов
/ 10 мая 2010

К сожалению, у меня нет времени, чтобы найти полное решение, но суть в том, чтобы использовать CTE с функцией NTILE http://msdn.microsoft.com/en-us/library/ms175126.aspx, чтобы разделить на 3 группы, а затем присоединиться к этому CTE в своем ОБНОВЛЕНИИ.и сделайте оператор CASE для группы NTILE, чтобы определить, использовать ли Value1, Value2 или Value3.

Редактировать См. Томас ответ для кода этого какпохоже, у него была та же идея!

1 голос
/ 10 мая 2010

Если ключи распределены равномерно, вы можете использовать оператор модуля (%) для выбора уникальных третей набора результатов.

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;
1 голос
/ 10 мая 2010

Для простого распределения создайте случайное ранжирование и по модулю на 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)

Вы можете изменить ORDER BY для ROW_NUMBER (), либо использовать NTILE и удалить по модулю

0 голосов
/ 10 мая 2010
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 в запросе на любое допустимое выражение, которое позволит вам определить «первую треть» по любым критериям.

0 голосов
/ 10 мая 2010

Интерпретируя то, что вы говорите буквально, вы могли бы нумеровать строки в возвращенном наборе строк, а затем выбирать различные сегменты на основе их номера строки.

например.

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...