【问题标题】:TSQL flag duplicate records with single unique idSQL 标记具有单个唯一 ID 的重复记录
【发布时间】:2013-08-03 07:43:15
【问题描述】:

必须有更好的方法来做到这一点。

我有一个表,我像这样标记了所有唯一记录:

    WITH
    CTE( TransId, OriginalName, StrippedName, RowNumber )
    AS
    (
        SELECT  TransID ,
                Name ,
                StrippedName,
                RN = ROW_NUMBER() OVER ( PARTITION BY StrippedName ORDER BY StrippedName )
        FROM    dbo.Members
    )

UPDATE  dbo.Members
SET ParenId = TransID
WHERE   TransID IN ( SELECT TransId FROM CTE WHERE RowNumber = 1 )

现在我想将所有重复记录(其中 RowNumber > 1)更新为唯一的 ParentId。现在我正在使用 UDF,它可以工作,但需要很长时间。这是 UDF:

CREATE FUNCTION dbo.getParentTransId ( @TransId INT, @strippedBusName VARCHAR(200) )
RETURNS INT
AS
BEGIN
    DECLARE @ParentTransId INT

    SELECT  @ParentTransId = TransId
    FROM    dbo.Members
    WHERE   StrippedBusName = @strippedBusName
      AND   ParenId IS NOT NULL

    IF  @ParentTransId IS NULL
    BEGIN
        SET @ParentTransId = @TransId
    END

    RETURN @ParentTransId
END
GO

这是我目前使用的更新语句:

UPDATE  dt
SET dt.ParenId = dbo.getParentTransId ( dt.TransID, dt.StrippedBusName )
FROM    dbo.Members dt
GO

有没有办法在不使用 UDF 的情况下进行相同的更新?

【问题讨论】:

    标签: sql-server tsql sql-update common-table-expression duplicate-data


    【解决方案1】:

    这是一个测试脚本,显示 @gotqn 答案有效:

    -- create table
    CREATE TABLE DupUpdateTest
    (
        Id      INT NOT NULL PRIMARY KEY IDENTITY( 1, 1 ),
        TransId INT NOT NULL,
        OriginalName    VARCHAR(MAX),
        StrippedName    VARCHAR(MAX),
        ParentId    INT NULL
    )
    GO
    
    -- insert data
    INSERT  INTO dbo.DupUpdateTest VALUES (2, 'name 1', 'name1', NULL)
    INSERT  INTO dbo.DupUpdateTest VALUES (3, 'name 1', 'name1', NULL)
    INSERT  INTO dbo.DupUpdateTest VALUES (6, 'name 1', 'name1', NULL)
    INSERT  INTO dbo.DupUpdateTest VALUES (8, 'name 2', 'name2', NULL)
    INSERT  INTO dbo.DupUpdateTest VALUES (11, 'name 2', 'name2', NULL)
    INSERT  INTO dbo.DupUpdateTest VALUES (15, 'name 55', 'name55', NULL)
    INSERT  INTO dbo.DupUpdateTest VALUES (23, 'name 55', 'name55', NULL)
    INSERT  INTO dbo.DupUpdateTest VALUES (99, 'name 100', 'name100', NULL)
    INSERT  INTO dbo.DupUpdateTest VALUES (122, 'name 108', 'name108', NULL)
    
    -- update parent id match
    UPDATE dt
    SET dt.ParentId = COALESCE(dt1.TransId, dt.TransId ) -- Returns the first nonnull expression among its arguments
    FROM  dbo.DupUpdateTest dt
    LEFT JOIN dbo.DupUpdateTest dt1
        ON dt.StrippedName   = dt1.StrippedName
    
    -- view results
    SELECT * FROM dbo.DupUpdateTest
    

    【讨论】:

      【解决方案2】:

      我想这应该可行:

      UPDATE  dbo.Members dt
      SET dt.ParenId = COALESCE( (SELECT TrandsID FROM dbo.Members WHERE  dt.StrippedBusName   = StrippedBusName  AND   ParenId IS NOT NULL), dt.TransId )
      

      我不确定,但以下方式应该更快:

      UPDATE  dbo.Members dt
      SET dt.ParenId = COALESCE(dt1.TransId, dt.TransId ) 
      FROM  dbo.Members dt
      LEFT JOIN dbo.Members dt1
          ON dt.StrippedBusName   = dt1.StrippedBusName
          AND  dt1.ParenId IS NOT NULL
      

      【讨论】:

      • 不错!更好的是,如果我在没有“AND dt1.ParentId IS NOT NULL”的情况下运行建议的最后一次更新,我就不必运行我的第一次更新来标记唯一性。
      猜你喜欢
      • 2015-11-26
      • 2013-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多