2010-05-10 5 views
2

Мне нужен способ получить набор результатов с KeyID и разделить его как можно более равномерно и обновлять записи по-разному для каждого подразделения на основе KeyID. Другими словами, существуетSQL Server/T-SQL: как обновить равные проценты набора результатов?

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) 

или что-то в этом роде. Спасибо за все ваши ответы.

ответ

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 
+0

@Martin Смит - Спасибо. Я скорректировал заявление Case. – Thomas

+0

Отлично! Brillian !! Только то, что мне нужно! Спасибо всем, кто ответил, особенно Мартин и Томас. – kenalacom

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) 
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) 

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

2

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

Редактировать См Thomas's ответа для кода для этого, как выглядит, как будто он имел ту же идею!

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

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; 
Смежные вопросы