根据其唯一ID更新号码

时间:2009-09-30 21:10:37

标签: sql-server

我在SQL Server中有一个表,其中每个唯一的location_id都有一个唯一的SiteNumber。我想要做的是,如果location_id不同,则将每个坐标值增加1。

例如:

SITENUM              LOCATION_ID
1234                 8801
4567                 8802
8910                 8803

......等等

让我们说,我现在为LOCATION_ID插入新值,但我的SITENUM仍为NULL

NULL                 7000
NULL                 7001
NULL                 7002
1234                 8801
4567                 8802

我的逻辑表明,7000的sitenum应该是MAX(select * sitenum from table) 但7001的下一个应该是Max(select * sitenum from table)+1

现在,以下代码一次将所有sitenums更新为完全相同的值

UPDATE dbo.[Monthly Hierarchy Table]
SET SITENUM = MAX(SELECT SITENUM FROM [Monthly Hierarchy Table])+1
WHERE SITENUM IS NULL and location_id is not null

但我真的希望它一行一行,查看max(sitenum)并根据非重复的location_id增加它。必须有一些方法可以将每个location_id与自身进行比较,并将satenumber增加到null,且location_id不同

我该怎么做呢?也许我理解它的方式不对,但这是一个非常简单的问题。

4 个答案:

答案 0 :(得分:1)

首先,你在错误的地方得到了MAX()函数,所以看起来应该是这样的:

UPDATE dbo.[Monthly Hierarchy Table]
SET SITENUM = (SELECT MAX(SITENUM)+1 FROM [Monthly Hierarchy Table])
WHERE SITENUM IS NULL and location_id is not null

不幸的是,这仍然无法帮助您,因为sql数据库通常会在更新任何行之前为所有行计算新值。这意味着你要将它们全部更新为相同的值。

相反,你需要在几个陈述中做到这一点:

BEGIN TRANSACTION
    DECLARE @NewSiteNum int
    SELECT @NewSiteNum = MAX(SiteNum)+1 FROM [Monthly Hierarchy Table]

    UPDATE dbo.[Monthly Hierarchy Table]
    SET SITENUM = SELECT @NewSiteNum,
        @NewSiteNum = @NewSiteNum + 1
    WHERE SITENUM IS NULL and location_id is not null
COMMIT

请注意此处的交易:这非常重要,或者您的SiteNums可能不会最终唯一。

答案 1 :(得分:0)

问题是聚合函数max()计算一次最大值,然后将该值应用于与where子句匹配的所有记录。它是事务性/ ACID兼容数据库的本质 - 在整个事务成功完成之前,对每个记录的单独更新都不是“可见的”。

您可能需要编写一个小存储过程,该过程使用循环遍历每个空sitenum记录的游标;不应该那么难。

答案 2 :(得分:0)

您可以这样做:

declare @num int;
set @num = (select max(LOCATION_ID) from MyTable);
update MyTable 
set SITENUM = @num, @num = @num + 1
where SITENUM is null and LOCATION_ID is not null

答案 3 :(得分:0)

以下是执行此任务的单个查询(无过程代码,递归或游标):

(我不确定你的问题是否该表可以有重复的locationIds,所以在我的解决方案中,具有相同locationIds的行会获得重复的sitenums)

drop table t
go
create table t (sitenum int, locid int)
go
insert into t(sitenum, locid) values (null, 7000)
insert into t(sitenum, locid) values (null, 7000)
insert into t(sitenum, locid) values (null, 7001)
insert into t(sitenum, locid) values (null, 7002)
insert into t(sitenum, locid) values (1234, 8801)
insert into t(sitenum, locid) values (4567, 8802)
go 

update t4 set sitenum = t3.new_sitenum from
t t4 inner join
(
    select t1.locid, COUNT(*) + (select MAX(sitenum) from t) as new_sitenum from
        (select locid from t where sitenum is null group by locid) as t1
        inner join
        (select locid from t where sitenum is null group by locid) as t2
        on t1.locid >= t2.locid
    group by t1.locid
) as t3
on t4.locid = t3.locid

select * from t

结果:

sitenum locId
4568    7000
4568    7000
4569    7001
4570    7002
1234    8801
4567    8802

关键是自己将表连接到自身。连接条件是

t1.locId> = t2.locId

然后按t1.locId进行分组,并使用COUNT(*)聚合为您提供一个有效数字,从每行的1开始计算。最里面的GROUP BYs可以处理重复的locIds。最后通过将locId加入子查询来更新。