2015-11-12 61 views
1

我正在清理电子商务网站上的客户列表。客户列表在客户ID和客户电子邮件之间具有多对多的关系。例如,客户可以在登录或匿名时使用同一电子邮件下订单,结果将是具有相同电子邮件但不同客户ID的两个客户记录。同样,客户可以在登录时使用两个不同的电子邮件创建订单,这将导致具有相同ID但不同电子邮件的客户记录。鉴于此,我想根据电子邮件或客户编号创建具有真正唯一ID的客户列表。此外,在某些情况下,电子邮件是空白的,因此客户记录都有空白的电子邮件,但不同的ID需要被视为两个不同的客户。SQL Server:根据两列生成唯一的客户密钥

所以给出这样的事情:

CUST_ID CUST_EMAIL 
------------------------ 
123  [email protected] 
123  [email protected] 
124  [email protected] 
125  [email protected] 
126 
127 
128  [email protected] 
128  [email protected] 
129  [email protected] 

我会想产生这样一个关键:

CUST_ID CUST_EMAIL  NEW_CUST_KEY 
------------------------------------ 
123  [email protected]  1 
123  [email protected]  1 
124  [email protected]  2 
125  [email protected]  2 
126       3 
127       4 
128  [email protected]  5 
128  [email protected]  5 
129  [email protected]  5 
+0

这是一次性转换还是可以在不改变现有数据的情况下重现的?我假定基于第一句话进行转换,那么为什么不在'WHILE'循环中做到这一点。然后,您可以与之前的记录进行比较,看看是否需要新ID。 – Steve

+0

我将需要每天运行此操作以合并新的客户记录,但只要记录分组正确,为给定客户生成的密钥是否每天都会发生变化并不重要。我很可能每天都会截断并重新加载目标表,所以任何可用作一次转换的东西都应该没问题。 – EvanMPW

+0

就WHILE循环而言,我不认为只和前一个记录进行比较是可行的。如果您查看上述示例中的最后一条记录,如果您之前将其与记录进行比较,则看起来它需要一个新的密钥(不同的电子邮件和ID)。但是,它确实与前两行共享一封电子邮件,这意味着所有三个应该被分组为具有相同新密钥的单个客户。 – EvanMPW

回答

1

OLDTABLE - 是你的表 newtable的 - WIL l具备导致

enter image description here

CREATE TABLE #NEWTABLE 
(
    NEW_CUST_KEY int not null , 
    CUST_ID int not null, 
    CUST_EMAIL nvarchar(100) null 
) 
------------------------------------ 
insert into #NEWTABLE (NEW_CUST_KEY,CUST_ID,CUST_EMAIL) 
SELECT ROW_NUMBER() OVER(ORDER BY CUST_ID, CUST_EMAIL) AS NEW_CUST_KEY, CUST_ID, CUST_EMAIL 
FROM 
(
    SELECT CUST_ID, CUST_EMAIL 
    FROM OLDTABLE 
    GROUP BY CUST_ID, CUST_EMAIL 
) T 


UPDATE Upd SET NEW_CUST_KEY = T.NEW_CUST_KEY 
FROM #NEWTABLE Upd 
join (
    SELECT CUST_ID, min(NEW_CUST_KEY) AS NEW_CUST_KEY 
    FROM #NEWTABLE 
    GROUP BY CUST_ID) T 
on Upd.CUST_ID = T.CUST_ID 

UPDATE Upd SET NEW_CUST_KEY = T.NEW_CUST_KEY 
FROM #NEWTABLE Upd 
join (
    SELECT CUST_EMAIL, min(NEW_CUST_KEY) AS NEW_CUST_KEY 
    FROM #NEWTABLE 
    GROUP BY CUST_EMAIL) T  
on nullif(Upd.CUST_EMAIL,'') = nullif(T.CUST_EMAIL,'')  

UPDATE Upd SET NEW_CUST_KEY = T.CHANGE_CUST_KEY 
FROM #NEWTABLE Upd 
join (
    SELECT NEW_CUST_KEY, ROW_NUMBER() OVER(ORDER BY NEW_CUST_KEY) AS CHANGE_CUST_KEY 
    FROM #NEWTABLE 
    GROUP BY NEW_CUST_KEY) T 
on Upd.NEW_CUST_KEY = T.NEW_CUST_KEY 

select * from #NEWTABLE 
+1

我忘记了空电子邮件。收集一行: on nullif(Upd.CUST_EMAIL,'')= nullif(T。CUST_EMAIL,'') –

+0

更新:在答案更改图片 –

0

我想你可以使用ROW_NUMBER ..... 这样的事情。 .....

SELECT DISTINCT CUST_ID, CUST_EMAIL 
ROW_NUMBER() OVER(PARTITION BY CUST_ID, CUST_EMAIL) AS New_Cust_Key 
FROM YOUR TABLES 
+0

ROW_NUMBER这里只会为每一行输出1,因为您正在通过CUST_ID和CUST_EMAIL进行分区,并且这已经是一个不同的列表。 – EvanMPW

0

我是想你的用户与他们的ID,以他们的电子邮件,反之亦然,当我创造了这个弗兰肯斯坦怪物查询结果地图:

DECLARE @Customers TABLE 
(
    CUST_ID INT 
    , CUST_EMAIL VARCHAR(20) 
); 

INSERT INTO @Customers (CUST_ID, CUST_EMAIL) 
VALUES (123, '[email protected]') 
    , (123, '[email protected]') 
    , (124, '[email protected]') 
    , (125, '[email protected]') 
    , (126, '') 
    , (127, '') 
    , (128, '[email protected]') 
    , (128, '[email protected]') 
    , (129, '[email protected]'); 


SELECT DISTINCT C.CUST_ID 
    , C.CUST_EMAIL 
    , DENSE_RANK() OVER(ORDER BY T.CUST_ID) AS NEW_CUST_KEY 
FROM @Customers AS C 
INNER JOIN (
    SELECT CUST_ID, CUST_EMAIL 
    FROM @Customers 
    EXCEPT 
    SELECT C2.CUST_ID, C2.CUST_EMAIL 
    FROM @Customers AS C1 
    INNER JOIN @Customers AS C2 
    ON C2.CUST_EMAIL = C1.CUST_EMAIL 
    AND C2.CUST_ID > C1.CUST_ID 
    AND C1.CUST_EMAIL <> '' 
) AS T 
    ON CASE 
    WHEN (T.CUST_ID = C.CUST_ID AND T.CUST_EMAIL = C.CUST_EMAIL AND T.CUST_EMAIL = '') THEN 1 
    WHEN (T.CUST_ID = C.CUST_ID OR T.CUST_EMAIL = C.CUST_EMAIL) AND T.CUST_EMAIL <> '' THEN 1 
    ELSE 0 
    END = 1; 

使用你的测试数据,它产生了这个,它确实看起来符合你的期望:

╔═════════╦═════════════════╦═══════════════╗ 
║ CUST_ID ║ CUST_EMAIL ║ NEW_CUST_KEY ║ 
╠═════════╬═════════════════╬═══════════════╣ 
║  123 ║ [email protected] ║    1 ║ 
║  123 ║ [email protected] ║    1 ║ 
║  124 ║ [email protected] ║    2 ║ 
║  125 ║ [email protected] ║    2 ║ 
║  126 ║     ║    3 ║ 
║  127 ║     ║    4 ║ 
║  128 ║ [email protected] ║    5 ║ 
║  128 ║ [email protected] ║    5 ║ 
║  129 ║ [email protected] ║    5 ║ 
╚═════════╩═════════════════╩═══════════════╝ 

你可以在现实生活中看到这个data.stackexchange.com

让我知道这是否适用于您的实际数据库。

+1

我在这里newby。感谢您访问data.stackexchange.com。非常有用的资源。 @Evaldas –

+0

@evaldas有没有办法解决这个问题,如果用户,如果列cust_id被替换为手机号码? –