【问题标题】:Consolidating values and deleting duplicates in a junction table using CTE使用 CTE 在联结表中合并值并删除重复项
【发布时间】:2010-04-20 20:24:09
【问题描述】:

我有以下架构:

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 有唯一约束。

解决此问题的最佳方法是什么?我考虑过删除约束,然后处理删除重复项(我曾经做过一次,可能会再做一次),但我希望有一种更简单的方法。

【问题讨论】:

    标签: sql-server tsql unique-constraint common-table-expression


    【解决方案1】:

    试试这样的:

    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 子句,只是因为如果您正在运行大型脚本,它可能会有所帮助。这样你就有了旧值和新值。

    【讨论】:

    • 嗯。这有点不对劲,我只是不够敏锐,无法掌握它。由于 parcelid 永远不会为空,因此我在 select 子查询中一直得到零结果。
    【解决方案2】:

    我最终放弃了约束并使用公用表表达式删除了重复项。
    这是我使用的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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-23
      • 2020-05-20
      • 1970-01-01
      • 2016-10-24
      • 1970-01-01
      • 2015-11-29
      相关资源
      最近更新 更多