将三列中共享某些值的行分组并为它们分配相同的 id

问题描述 投票:0回答:1

我在 SQL Server 上遇到问题。我有一个与此示例类似的表:

| RegisterId | Name           | Phone  | Email                    |
|------------|----------------|--------|--------------------------|
| XXX-00001  | John Strauss   | 241567 | Null                     |
| XXX-00023  | Rick Astley    | 241567 | [email protected]  |
| XXX-00003  | John Strauss   | NULL   | NULL                     |
| XXX-00099  | NULL           | 241567 | [email protected] |
| XXX-00085  | NULL           | 256819 | [email protected]  |
| XXX-00016  | NULL           | NULL   | [email protected] |
| XXX-00007  | John Deep      | 280933 | NULL                     |
| XXX-00008  | John Deep      | 93484  | NULL                     |
| XXX-00009  | Javier Estrada | 94578  | [email protected]         |

您可以注意到我有重复的值。这是因为它们对应于同一个用户。发生这种情况的原因是这些值可能来自不同的数据库。 我想为他们分配一个新 ID,以将他们识别为同一个用户(理应如此),如果他们有:

  • 同一部手机
  • 同名
  • 同一个电子邮件

类似这样的:

| RegisterId | Name           | Phone  | Email                    | UserId |
|------------|----------------|--------|--------------------------|--------|
| XXX-00001  | John Strauss   | 241567 | Null                     | 1      |
| XXX-00023  | Rick Astley    | 241567 | [email protected]  | 1      |
| XXX-00003  | John Strauss   | NULL   | NULL                     | 1      |
| XXX-00099  | NULL           | 241567 | [email protected] | 1      |
| XXX-00085  | NULL           | 256819 | [email protected]  | 1      |
| XXX-00016  | NULL           | NULL   | [email protected] | 1      |
| XXX-00007  | John Deep      | 280933 | NULL                     | 2      |
| XXX-00008  | John Deep      | 93484  | NULL                     | 2      |
| XXX-00009  | Javier Estrada | 94578  | [email protected]         | 3      |

我尝试了 SQL 中的许多功能,甚至是一些 CTE,但我就是找不到实现它的方法。有人可以告诉我应该使用哪种近似值来解决这个问题吗?

dbFiddle

sql sql-server
1个回答
0
投票

总是可能存在冲突,并且根据您开始使用的用户,您可以获得不同的用户分组,但这是我的尝试:

--Pick one user
DECLARE @name varchar(200);
SET @name = (SELECT TOP(1) Name FROM Registers WHERE Name IS NOT NULL AND UserID IS NULL);
WHILE @name IS NOT NULL
BEGIN
    PRINT '@name: '+@name;

    --Get the next available UserID for this user
    DECLARE @nextUserID int    = (SELECT ISNULL(MAX(UserID), 0)+1 FROM Registers WHERE UserID IS NOT NULL);
    PRINT '   @nextUserID: int = '+CAST(@nextUserID AS varchar);

    -- Give the user their new userID
    UPDATE Registers SET UserID = @nextUserID WHERE UserID IS NULL AND Name = @name;

    --Keep looking for other rows that match this user in some way
    DECLARE @rc int = 1;
    WHILE @rc > 0 
    BEGIN
        UPDATE Registers 
        SET UserID = @nextUserID 
        WHERE UserID IS NULL 
        AND (
            Name  IN (SELECT Name  FROM Registers WHERE UserID = @nextUserID)
            OR
            Phone IN (SELECT Phone FROM Registers WHERE UserID = @nextUserID)
            OR
            Email IN (SELECT Email FROM Registers WHERE UserID = @nextUserID)
        )
        SET @rc = @@ROWCOUNT;
        PRINT '   Rows updated: @rc='+CAST(@rc AS varchar);
        --SELECT * FROM Registers
    END

    SET @name = (SELECT TOP(1) Name FROM Registers WHERE Name IS NOT NULL AND UserID IS NULL);
END

SELECT * FROM Registers
ORDER BY UserID;

给出结果:

| RegisterID | Name           | Phone  | Email                    | UserID |
|------------|----------------|--------|--------------------------|--------|
| XXX-00001  | John Strauss   | 241567 | null                     | 1      |
| XXX-00003  | John Strauss   | null   | null                     | 1      |
| XXX-00016  | null           | null   | [email protected] | 1      |
| XXX-00023  | Rick Astley    | 241567 | [email protected]  | 1      |
| XXX-00085  | null           | 256819 | [email protected]  | 1      |
| XXX-00099  | null           | 241567 | [email protected] | 1      |
| XXX-00007  | John Deep      | 280933 | null                     | 2      |
| XXX-00008  | John Deep      | 93484  | null                     | 2      |
| XXX-00009  | Javier Estrada | 94578  | [email protected]         | 3      |
@name: John Strauss
   @nextUserID: int = 1
   Rows updated: @rc=2
   Rows updated: @rc=2
   Rows updated: @rc=0
@name: John Deep
   @nextUserID: int = 2
   Rows updated: @rc=0
@name: Javier Estrada
   @nextUserID: int = 3
   Rows updated: @rc=0

dbFiddle

© www.soinside.com 2019 - 2024. All rights reserved.