简体   繁体   English

SQL 查询根据另一列中的最大值更新记录

[英]SQL query to update a record based on the max value in another column

The Problem问题

I have this table.我有这张桌子。 (You can also view it in DBFiddle .) (您也可以在DBFiddle中查看它。)

Id ID Version版本 Item No.编号。 Notes笔记
1 1个 NULL NULL 31 31
2 2个 1 1个 31 31 tasty可口
3 3个 2 2个 31 31 kinda tasty有点好吃
4 4个 NULL NULL 32 32
5 5个 1 1个 32 32 meh
6 6个 2 2个 32 32 alright好吧
7 7 3 3个 32 32 fabulous极好
8 8个 NULL NULL 33 33 ambivalent矛盾的
9 9 1 1个 33 33 gross总的
10 10 2 2个 33 33 puke呕吐物

The 1st column is the primary key.第一列是主键。 The 2nd and 3rd column are integers.第二和第三列是整数。 The 4th column is a VARCHAR.第 4 列是 VARCHAR。

For every unique Item No. where its Version is NULL, I want to look at the record with the highest Version value, take the content of its Notes field, and copy it over.对于版本为 NULL 的每个唯一项目编号,我想查看版本值最高的记录,将其注释字段的内容复制过来。

This is much easier to understand visually;这在视觉上更容易理解; after the command is run, the table should look like this:命令运行后,表格应如下所示:

Id ID Version版本 Item No.编号。 Notes笔记
1 1个 NULL NULL 31 31 kinda tasty有点好吃
2 2个 1 1个 31 31 tasty可口
3 3个 2 2个 31 31 kinda tasty有点好吃
4 4个 NULL NULL 32 32 fabulous极好
5 5个 1 1个 32 32 meh
6 6个 2 2个 32 32 alright好吧
7 7 3 3个 32 32 fabulous极好
8 8个 NULL NULL 33 33 ambivalent矛盾的
9 9 1 1个 33 33 gross总的
10 10 2 2个 33 33 puke呕吐物

Explanation of the Changes变动说明

  • for Item No. 31, "kinda tasty" was copied over because it's in the record with the highest Version number, and the target cell is not occupied.对于第 31 项,“kinda tasty”被复制过来,因为它在版本号最高的记录中,目标单元格未被占用。
  • for Item No. 32, "fabulous" was copied over for the same reason.对于第 32 项,“fabulous”出于同样的原因被复制了过来。
  • "puke" was NOT copied over to replace "ambivalent", because the target cell is occupied. “puke”未被复制以替换“ambivalent”,因为目标单元格已被占用。

The Question问题

What is the query to achieve this in SQL Server?在 SQL 服务器中实现此目的的查询是什么?

I know that I need a way of grouping records together by Item No. , find the one with the highest Version value, take its Notes value, and copy it to the record where the Version is NULL, but I am having trouble translating this to SQL.我知道我需要一种按Item No.将记录分组的方法,找到版本值最高的那个,取其注释值,并将其复制到版本为 NULL 的记录中,但我无法将其转换为SQL。

Try this:尝试这个:

UPDATE t SET notes = (
   SELECT TOP 1 s.notes 
   FROM t s 
   WHERE s.item_no = t.item_no 
   ORDER BY version DESC
) WHERE version IS NULL AND notes IS NULL

Check demo检查演示

Use an updatable CTE:使用可更新的 CTE:

WITH cte AS (
  SELECT *, FIRST_VALUE(Notes) OVER (PARTITION BY ItemNo ORDER BY Version DESC) newNotes 
  FROM tablename
)
UPDATE cte
SET Notes = newNotes
WHERE Version IS NULL AND Notes IS NULL;

See the demo .请参阅演示

Create a CTE to determine the value we need to update to, and then join that to your original table with update join syntax:创建一个 CTE 以确定我们需要更新的值,然后使用更新连接语法将其连接到原始表:

with maxVal as
(
    select row_number() over (partition by [Item No.] order by Version desc) rn
        , notes
        , [Item No.]
    from TestTable
    where Version is not null
)
update TestTable
set Notes = maxVal.Notes
from TestTable
left join maxVal
    on TestTable.[Item No.] = maxVal.[Item No.]
    and maxVal.rn = 1
where TestTable.Version is null
    and TestTable.Notes = ''

You can try this approach:您可以尝试这种方法:

-- Preparing a table variable
DECLARE @table1 AS TABLE (
    id  INT IDENTITY(1,1) NOT NULL,
    VersionID INT,
    ItemNo INT,
    Note Varchar(50)
)

insert into 
    @table1 (VersionID,ItemNo,Note)
values 
    (NULL,31,''),
    (1,31,'tasty'),
    (2,31,'kinda tasty'),
    (NULL,32,''),
    (1,32,'meh'),
    (2,32,'alright'),
    (3,32,'fabulous'),
    (NULL,33,'ambivalent'),
    (1,33,'gross'),
    (2,33,'puke');

-- update section 
update up set up.Note = db.Note
from @table1 up
inner join 
(
    select a.ItemNo,a.Note
    from @table1 a
    inner join 
    (
        select itemNo,Max(VersionID) as vs
        from @table1
        where Note <> ''
        group by itemNo
    ) as b on a.ItemNo = b.ItemNo and a.VersionID = b.vs
) as db on db.ItemNo = up.ItemNo and up.Note = ''


-- result
select * from @table1

You can select the maximum value for each " Item No. ", then update the original table with the corresponding value where the " Notes " is NULL.您可以为每个“ Item No. ”选择最大值,然后用“ Notes ”为NULL的相应值更新原始表。

UPDATE tab 
SET [Notes] = t2.[Notes]
FROM       tab t1 
INNER JOIN (SELECT *, MAX(Version) OVER(PARTITION BY [Item No.]) AS Max_Version
            FROM tab)  t2
        ON t1.[Item No.] = t2.[Item No.]
       AND t2.[Version]  = t2.[Max_Version]
       AND t1.[Notes] IS NULL

Check the demo here .此处查看演示。

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

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