2009-09-30 86 views
0

我在SQL Server中有一个表,其中每个唯一的location_id都有一个唯一的SiteNumber。我想要做的是,如果location_id不同,请将每个sitenumber加1。根据其唯一ID更新号码

例如:

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下一个sitenum应该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与自身进行比较,然后将sitenumber增加到无论其为null还是location_id不同的地方

我该如何去做这件事?也许我理解它的方式不对,但它是一个非常简单的问题。

回答

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 BY在那里可以处理重复的locIds。最后通过将locId加入子查询进行更新。

+0

我loc.id的都是独一无二的,这种解决方案实际上是一个相当位更好的正弦e我可以引用我的loc.id并根据相同的值对它们进行分组。实际上这对我的问题非常有效;) – Sonal 2009-10-01 13:48:23

0

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

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

+0

以下代码也不起作用,返回“=”附近的语法错误 declare @i int; set @ i = 0; 而(从new_locations SELECT COUNT(store_code))@i <= \t开始 \t \t UPDATE DBO。[每月层次结构表] \t \t \t SET SITENUM = MAX((SELECT SITENUM FROM [每月层次结构表])+ 1 , \t \t \t \t @i = @ i + 1的 \t \t其中sitenum为空\t \t END – Sonal 2009-09-30 21:28:30

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 
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可能最终不会是唯一的。

+0

这个作品真的很好。谢谢! – Sonal 2009-10-01 13:41:39