3

我在为在网格中显示数据而必须构建的 SQL 请求时遇到了一些问题。

我有如下临时表(我在示例中输入了数字而不是电子邮件地址):

GroupID | Email1 | Email2 
null    |   1    | 2
null    |   1    | 2
null    |   1    | null
null    |   3    | 1
null    |   2    | 2
null    |   4    | 2
null    |   5    | 6
null    |   6    | null

我需要更新表以设置 GroupID,如下所述:如果 email1 或 email2 匹配任何其他记录,则该记录需要与另一个记录具有相同的 groupId。例如(使用上表):

GroupID | Email1 | Email2
**1**   |   1    | 2
**1**   |   1    | 2
**1**   |   1    | null
**1**   |   3    | 1
**1**   |   2    | 2
**1**   |   4    | 2
**2**   |   5    | 6
**2**   |   6    | null

我尝试过这样的事情:

UPDATE a
SET a.GroupId = b.GroupId
FROM   #temp a
INNER JOIN (SELECT Email, 
                   ROW_NUMBER() OVER (ORDER BY ISNULL(Email,'zzzzzzzz')) GroupId
            FROM (SELECT Email1 Email
                  FROM #temp
                  GROUP BY Email1
                  UNION ALL 
                  SELECT Email2 Email   
                  FROM #temp                
                  GROUP BY Email2 
                 ) c
            GROUP BY Email
           ) b
ON a.Email1 = b.Email OR
   a.Email2 = b.Email OR 
   (b.Email IS NULL AND a.Email1 IS NULL AND a.Email2 IS NULL)

但这不起作用我打算...例如,Email2等于Email 1的情况不被识别为同一组...我怎样才能使这个请求按我的意愿工作?甚至有可能吗?

[编辑] 2013/15/17 14:15:事实上,对于规则,我的意思是“如果 email1 或 email 2 与任何其他记录的 email1 或 email2 匹配,则应该属于相同的 groupID”

4

1 回答 1

4

这不能一次执行,JOIN因为可能有很长的电子邮件链需要遍历,例如1, 2-> 2, 3-> 3, 4-> ... -> 99, 100。(您可以使用递归 CTE 在单个语句中执行此操作——以某种方式解决GROUP BY问题——但您知道我的意思。)

这是一种方法(SQL Server 2005 及更高版本):

WITH E AS (
   SELECT
      Num = Row_Number() OVER (ORDER BY (SELECT 1)),
      *
   FROM dbo.EmailGroups
)
UPDATE E
SET E.GroupID = E.Num
;

WHILE @@RowCount > 0 BEGIN
   UPDATE E
   SET E.GroupID = X.MinGroupID
   FROM
      dbo.EmailGroups E
      INNER JOIN (
         SELECT
            E1.GroupID,
            MinGroupID = Min(E2.GroupID)
         FROM
            dbo.EmailGroups E1
            INNER JOIN dbo.EmailGroups E2
               ON E1.Email1 IN (E2.Email1, E2.Email2)
               OR E1.Email2 IN (E2.Email1, E2.Email2)
         GROUP BY
            E1.GroupID
         HAVING
            E1.GroupID <> Min(E2.GroupID)
      ) X ON E.GroupID = X.GroupID
   ;
END;

看到这个在 SQL Fiddle 中工作

这将导致每组链接的行具有相同的GroupID,与其他所有不同的行GroupIDs(但它们不会是连续的,会有间隙)。如果您需要它们是连续的,请执行最终更新以将其设置GroupIDDENSE_RANK() OVER (ORDER BY GroupID)- 这在 Fiddle 中显示。

于 2013-05-17T18:18:15.097 回答