Как обновить ТОП 5, используя подвыбор? - PullRequest
2 голосов
/ 03 августа 2009

Я был удивлен, увидев, что следующие обновленные 34 строки ... не 5:

UPDATE 
 Message
 SET StatusRawCode = 25
WHERE StatusRawCode in
  ( 
     Select TOP 5 
      M2.StatusRawCode
       From Message as M2
        Where M2.StatusRawCode = 5
  ) 

Любые идеи о том, как придать этому правильную форму?

Спасибо!

Ответы [ 6 ]

4 голосов
/ 03 августа 2009

Я предполагаю, что значения StatusRawCode, возвращаемые из вашего подзапроса, являются значениями, использованными в 34 записях, которые были обновлены. Вместо

WHERE StatusRawCode IN

Используйте это:

UPDATE 
    Message
SET StatusRawCode = 25
    WHERE PrimaryKey in
    ( 
        Select TOP 5 
            PrimaryKey
        From Message as M2
        Where M2.StatusRawCode = 5
    )

По сути, вы будете выбирать первичные ключи из 5 строк, которые будут обновлены в подзапросе. Имейте в виду, что это обновит только первые 5 записей на основе упорядоченного кластеризованного индекса вашей таблицы. Вы захотите добавить заказ по предложению, если вам нужно указать конкретные критерии для записей TOP 5.

Например, если есть столбец под названием «Ранг», который вы хотите использовать в качестве критерия, напишите запрос следующим образом:

UPDATE 
    Message
SET 
    StatusRawCode = 25
WHERE 
    PrimaryKey IN
    ( 
        SELECT TOP 5 
            PrimaryKey
        FROM 
            Message as M2
        WHERE 
            M2.StatusRawCode = 5
        ORDER BY
            Rank DESC
    )

Это даст вам ТОП 5 записей на основе значений столбца Ранг. При необходимости вы можете заменить свой столбец.

2 голосов
/ 03 августа 2009

Похоже, что StatusRawCode далеко не уникален. Вы хотите получить первичный ключ или другой уникальный столбец, чтобы определить пятерку лидеров. Вы обновляете любую строку, где StatusRawCode равно 5. Очевидно, есть 34 строки, которые удовлетворяют этому условию.

Более того, top 5 будет означать только что-либо с предложением order by. SQL Server не хранит строки в каком-либо определенном порядке, и вы не будете гарантированно возвращать одни и те же пять строк каждый раз. SQL Server хранит строки в 8k-страницах, и это не гарантирует и не обеспечивает согласованность заказ для вашего набора строк. Вы не можете полагаться на это, и вы должны использовать order by, чтобы убедиться, что вы получаете правильные пять строк. В противном случае вы будете обновлять пять случайных строк .

2 голосов
/ 03 августа 2009

Есть ли способ четко определить ТОП 5 строк?

Согласно вашему запросу, не имеет значения, если вы делаете TOP 5 (потому что вы выбираете записи с StatusRawCode = 5). Таким образом, ваш запрос такой же, как

UPDATE 
 Message
 SET StatusRawCode = 25
WHERE StatusRawCode = 5
1 голос
/ 03 августа 2009

Вам необходимо поставить условие IN на уникальный первичный ключ.

В SQL 2K5 и более поздних версиях вы также можете использовать CTE:

  WITH cte AS (
     Select TOP 5 
      M2.StatusRawCode
       From Message as M2
        Where M2.StatusRawCode = 5
    ORDER BY ...
  )
  UPDATE cte 
  SET StatusRawCode = 25
0 голосов
/ 03 августа 2009

Если у вас нет первичного ключа и CTE недоступны, будет работать также следующее:

UPDATE M
SET StatusRawCode = 25
FROM (Select TOP 5 
    M2.StatusRawCode
    FROM Message as M2
    WHERE M2.StatusRawCode = 5
    ORDER BY ...) M
0 голосов
/ 03 августа 2009

Я хотел бы включить и рекомендовать всегда начинать оператор UPDATE с оператора SELECT. Как это:

SELECT * 
--UPDATE m SET StatusRawCode = 25
FROM Message m
WHERE StatusRawCode in  (
        Select TOP 5
       M2.StatusRawCode
       From Message as M2
       Where M2.StatusRawCode = 5  
);

... но обязательно приведите ваш запрос в соответствие с вашими фактическими требованиями, как только вы поймете, где вы идете не так (что в этом случае, вероятно, будет похоже на ответ KG)

Это покажет вам строки, которые будут затронуты вашим запросом ... поэтому, как только вы сделаете это правильно, измените SELECT * для строки UPDATE (в настоящее время прокомментированной), и вы должны получить предсказуемые результаты.

Имейте в виду, однако, что UPDATE не поддерживает ORDER BY, поэтому, если вы в конечном итоге попробуете UPDATE TOP (5) ..., вы не получите желаемых результатов.

Rob

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...