我有以下架构:
Parcels Segments SegmentsParcels
========= ========== =================
ParcelID SegmentID ParcelID
... Name SegmentID
... id
数据的用户希望合并Segments.Names并给我一个映射到新Segment.Names的当前Segment.Names列表(所有这些都存在)。
所以现在我将这个列表放在一个临时表中,其中currentID和newID映射到。
我想要做的是根据此地图更新SegmentsParcels中的SegmentID。我可以使用声明:
update SegmentParcels set segmentID = [newID] from newsegments where segmentID = currentid
但这会产生一些重复项,我对SegmentParcels中的ParcelID和SegmentID有唯一约束。
最好的方法是什么?我考虑删除约束,然后处理删除重复项(我在某一点上做了,可能再做一次),但我希望有一种更简单的方法。
答案 0 :(得分:0)
尝试这样的事情:
CREATE TABLE #Results (oldID int, newid int)
update sp
set segmentID = dt.newID
OUTPUT sp.segmentID, dt.newID
INTO #Results
FROM SegmentParcels sp
INNER JOIN (SELECT DISTINCT
segmentID, newID
FROM newsegments ns
INNER JOIN SegmentParcels sp ON ns.currentid = sp.segmentID
LEFT OUTER JOIN SegmentParcels sp2 ON ns.currentid = sp2.segmentID AND sp.ParcelID=sp2.ParcelID
WHERE sp2.ParcelID IS NULL
) dt ON dt.segmentID=sp.segmentID
我投入了SQL Server 2005及更高版本的OUTPUT子句,只是因为如果你有一个大脚本运行它可能会有所帮助。这样你就有了旧的和新的价值。
答案 1 :(得分:0)
我最终放弃了约束并使用公用表表达式删除了重复项 这是我使用的sql:
-- drop unique constraint
ALTER TABLE [dbo].[SegmentParcels] DROP CONSTRAINT [uc_SegmentID_ParcelID]
GO
-- update segment ids to new values from map
update SegmentParcels
set segmentID = [newID] from newsegments where segmentID = currentid
GO
-- use common table expression to delete duplicates
WITH Duplicates(SegmentID, ParcelID, Id)
AS
(
SELECT SegmentID, ParcelID, Min(Id) Id
FROM SegmentParcels
GROUP BY segmentID, parcelID
HAVING Count(*) > 1
)
DELETE FROM SegmentParcels
WHERE Id IN (
SELECT SegmentParcels.Id
FROM SegmentParcels
INNER JOIN Duplicates
ON SegmentParcels.segmentID = Duplicates.SegmentID
AND SegmentParcels.parcelID = Duplicates.ParcelID
AND SegmentParcels.Id <> Duplicates.Id
)
-- add unique constraint back
ALTER TABLE [dbo].[SegmentParcels] ADD CONSTRAINT [uc_SegmentID_ParcelID] UNIQUE NONCLUSTERED
(
[segmentID] ASC,
[parcelID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO