简体   繁体   English

如何使用subselect更新TOP 5?

[英]How do I UPDATE TOP 5, using a subselect?

I was surprised to see that the following updated 34 rows...not 5: 我惊讶地发现以下更新了34行...而不是5行:

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

Any ideas on how to pound this into the right shape? 关于如何将其打造成正确形状的任何想法?

Thank you! 谢谢!

My guess is the StatusRawCode values returned from your sub query are values used in the 34 records that were updated. 我的猜测是从您的子查询返回的StatusRawCode值是在更新的34条记录中使用的值。 Instead of 代替

WHERE StatusRawCode IN

Use this: 用这个:

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

In essence, you will be selecting the primary keys of the 5 rows to be updated in the sub query. 实质上,您将在子查询中选择要更新的5行的主键。 Keep in mind this will update only the top 5 records based on the clustered index ordering of your table. 请记住,这将根据表的聚簇索引顺序仅更新前5条记录。 You will want to add an order by clause if you need to specify a specific criteria for the TOP 5 records. 如果需要为TOP 5记录指定特定条件,则需要添加order by子句。

For example, if there is a column called Rank that you want to use as the criteria, write your query like so: 例如,如果有一个名为Rank的列要用作条件,请按如下方式编写查询:

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

This will give you the TOP 5 records based on the Rank column values. 这将根据Rank列值为您提供前5个记录。 You can substitute for your column as necessary. 您可以根据需要替换列。

Is there a way to distinctly identify the TOP 5 rows? 有没有办法明确识别TOP 5行?

As per your query, it doesn't matter if you do TOP 5 (because you are selecting records with StatusRawCode = 5). 根据您的查询,如果您执行TOP 5并不重要(因为您选择StatusRawCode = 5的记录)。 So, in a way your query is same as 所以,在某种程度上你的查询是相同的

UPDATE 
 Message
 SET StatusRawCode = 25
WHERE StatusRawCode = 5

It appears that StatusRawCode is far from unique. 似乎StatusRawCode远非唯一。 You want to pull back the primary key, or another unique column to identify the top five. 您想要撤回主键或其他唯一列以识别前五个。 You're updating any row where StatusRawCode is equal to 5. Apparently, there are 34 rows which meet that condition. 您正在更新StatusRawCode等于5的任何行。显然,有34行符合该条件。

Moreover, top 5 will only mean anything with an order by clause. 此外, top 5只表示任何带有order by子句的东西。 SQL Server does not store rows in any particular order, and you will not be guaranteed to get the same five rows back every time. SQL Server不以任何特定顺序存储行,并且不保证每次都返回相同的五行。 SQL Server stores rows in 8k pages, and it does not guarantee nor provide a consistent order for your row set. SQL Server以8k页为单位存储行,并且不保证也不为行集提供一致的顺序。 You cannot rely on this, and you must use an order by to ensure that you're getting the correct five rows. 您不能依赖于此,您必须使用order by来确保您获得正确的五行。 Otherwise, you'll be updating five random rows . 否则,您将更新五个随机行

You need to put the IN condition on an unique, primary key. 您需要将IN条件放在唯一的主键上。

In SQL 2K5 and forward you can also use a CTE: 在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

I'd like to pitch in and recommend that you always start an UPDATE statement with SELECT statement. 我想介入并建议您始终使用SELECT语句启动UPDATE语句。 Like this: 像这样:

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

...but definitely fix up your query to your actual requirements, once you can see where you're going wrong (which in this case, would probably be similar to KG's response) ...但是一旦你能看到你出错的地方(在这种情况下,可能与KG的回应类似),肯定会根据你的实际要求修改你的查询

This will show you the rows that will be affected by your query... so once you have this correct, change the SELECT * for the UPDATE row (currently commented), and you should get predictable results. 这将显示将受您的查询影响的行...所以一旦你有了正确的,更改UPDATE行的SELECT *(当前已注释),你应该得到可预测的结果。

Bear in mind though, that UPDATE doesn't support ORDER BY, so if you end up trying UPDATE TOP (5)..., then you won't get the results you want. 但请记住,UPDATE不支持ORDER BY,所以如果你最终尝试UPDATE TOP(5)...,那么你将无法得到你想要的结果。

Rob

If you don't have a primary key and CTEs are not available, the following will also work: 如果您没有主键且CTE不可用,则以下内容也适用:

UPDATE M
SET StatusRawCode = 25
FROM (Select TOP 5 
    M2.StatusRawCode
    FROM Message as M2
    WHERE M2.StatusRawCode = 5
    ORDER BY ...) M

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM