2009-09-30 113 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