如果一个连接按每个rep id工作,请不要再加入

时间:2018-02-06 20:25:49

标签: sql amazon-redshift

我匹配导入Redshift DB的两个数据集:两者都处于rep id级别。

这是我匹配两个数据集的初始查询:

select * 
from #t t
join #t2 t2
on lower(trim(t.unique_id))=lower(trim(t2.unique_id))
or lower(trim(t.email))=lower(trim(t2.email)) 
or lower(trim(split_part(t.first_name,',',1))||trim(split_part(t.last_name,',',1)))=lower(trim(split_part(t2.first_name,',',1))||trim(split_part(t2.last_name,',',1))) 

#t是我匹配的真实来源,unique_id被认为是re​​p id(内部标识符)的通用标识符(尽管只匹配约60%),但是,在某些情况下#t2表每个代表(错误地)多个unique_id s,并且错误地多个email s。

如何更改它以使其更具限制性,即。当通过unique_id获得匹配时 - 不匹配该代表的下一条记录,当匹配email时 - 不匹配该代表的下一条记录,最后通过名字/姓氏加入。

谢谢!

1 个答案:

答案 0 :(得分:1)

我认为有几种方法可以给这只猫上皮。作为一个选项,您可以将每个联接的排名添加为CASE语句,然后选择具有最小排名的那个:

<p>From left to right: name1, name2, name3, name4</p>

您也可以通过查询两次,一次获取数据,一次获得最小值(ranktest)来完成此操作。它几乎肯定会慢一点,但是......它有点漂亮:

SELECT *
FROM
(
    SELECT *,
        min(ranktest) OVER (PARTITION BY t1.unique_id) as minrank
    FROM
    (
        select *,
        CASE WHEN lower(trim(t.unique_id))=lower(trim(t2.unique_id)) THEN 1
             WHEN lower(trim(t.email))=lower(trim(t2.email))  THEN 2 
             WHEN ower(trim(split_part(t.first_name,',',1))||trim(split_part(t.last_name,',',1)))=lower(trim(split_part(t2.first_name,',',1))||trim(split_part(t2.last_name,',',1))) THEN 3 
             END as ranktest
        from #t t
            join #t2 t2
                on lower(trim(t.unique_id))=lower(trim(t2.unique_id))
                or lower(trim(t.email))=lower(trim(t2.email)) 
                or lower(trim(split_part(t.first_name,',',1))||trim(split_part(t.last_name,',',1)))=lower(trim(split_part(t2.first_name,',',1))||trim(split_part(t2.last_name,',',1)))
    ) sub1
WHERE ranktest = minrank;

或者,您可以将其作为UNION ALL运行,每次都以不同的方式测试连接,以避免重复,并且只允许排名最高的连接:

WITH subquery AS
(
    select *,
            CASE WHEN lower(trim(t.unique_id))=lower(trim(t2.unique_id)) THEN 1
                 WHEN lower(trim(t.email))=lower(trim(t2.email))  THEN 2 
                 WHEN ower(trim(split_part(t.first_name,',',1))||trim(split_part(t.last_name,',',1)))=lower(trim(split_part(t2.first_name,',',1))||trim(split_part(t2.last_name,',',1))) THEN 3 
                 END as ranktest
            from #t t
                join #t2 t2
                    on lower(trim(t.unique_id))=lower(trim(t2.unique_id))
                    or lower(trim(t.email))=lower(trim(t2.email)) 
                    or lower(trim(split_part(t.first_name,',',1))||trim(split_part(t.last_name,',',1)))=lower(trim(split_part(t2.first_name,',',1))||trim(split_part(t2.last_name,',',1)))
)
SELECT *
FROM subquery t1
WHERE t1.ranktest = (SELECT min(ranktest) FROM subquery WHERE subquery.unique_id = t1.ranktest)