2017-05-17 70 views
0

我正在根據僱主的數據找出重複的僱主根據他們的名字。sql查詢找到潛在的重複記錄

的數據是這樣的:

Employer ID | Legal Name | Operating Name 
------------- | ---------------| -------------------- 
1    |  AA  |  AA 
2    |  BB  |  AA 
3    |  CC  |  BB 
4    |  DD  |  DD 
5    |  ZZ  |  ZZ 

現在,如果我試圖找到僱主AA的所有重複的查詢應該返回以下結果:

Employer ID | Legal Name | Operating Name 
------------- | ---------------| -------------------- 
1    |  AA  |  AA 
2    |  BB  |  AA 
3    |  CC  |  BB 

僱主1的法定名稱和單位2的操作名稱是與搜索的直接匹配。 但是,捕獲的是僱主3,它與搜索字符串沒有直接關係,但僱主2的合法名稱與僱主3的工作名稱相匹配。

而我需要的搜索結果達到第n級。我不確定這是否可以通過類似這樣的遞歸查詢來實現。

請幫

我試圖通過遞歸CTE來實現這一點,但後來我意識到,這是進入無限遞歸。下面是代碼:

DECLARE @SearchName VARCHAR(50) 
    SET @SearchName = 'AA' 
    ;With CTE_EmployerNames 
    AS 
    (
-- Anchor Member definition 
select * 
from [dbo].[Name_Table] 
where Leg_Name = @SearchName 
OR  Op_Name = @SearchName 
UNION ALL 
-- Recursive Member definition 
select N.* 
from [dbo].[Name_Table] N 
JOIN CTE_EmployerNames C 
ON  N.ID <> C.ID 
AND  (N.Leg_Name = C.Leg_Name 
OR  N.Leg_Name = C.Op_Name 
OR  N.Op_Name = C.Leg_Name 
OR  N.Op_Name = C.Op_Name) 
    ) 

    select * 
    from CTE_EmployerNames 

更新: 我創建了一個存儲過程來達到我想要的。但是由於循環和遊標,這個過程有點慢。截至目前,這正在解決我的問題,幾乎不影響執行時間。任何建議來優化它或另一種方式來做到這一點將不勝感激。多謝你們。這裏是代碼:

CREATE PROCEDURE [dbo].[Get_Similar_Name_Employers] 
@P_BaseName VARCHAR(100) 
AS 
BEGIN 
DECLARE @ID INT 
DECLARE @Leg_Name VARCHAR(50) 
DECLARE @Op_Name VARCHAR(50) 

-- Create temp table to hold data temporarily 
CREATE TABLE #Temp_Employers 
(
    [ID] [int] NULL, 
    [Leg_Name] [varchar](50) NULL, 
    [Op_Name] [varchar](50) NULL, 
    [Status] [bit] null -- To keep track if that record is processed or not 
) 

-- Insert all records which are directly matching with search criteria 
INSERT INTO #Temp_Employers 
SELECT NT.ID, NT.Leg_Name, NT.Op_Name, 0 
FROM dbo.Name_Table NT 
WHERE NT.Leg_Name = @P_BaseName 
OR  NT.Op_Name = @P_BaseName 

while EXISTS (SELECT 1 from #Temp_Employers where Status = 0) -- until all rows are processed 
BEGIN 
    DECLARE @EmployerCursor CURSOR 
    SET  @EmployerCursor = CURSOR FAST_FORWARD 
    FOR 
      SELECT ID, Leg_Name, Op_Name 
      from #Temp_Employers 
      where Status = 0 

    OPEN @EmployerCursor 

    FETCH NEXT 
    FROM @EmployerCursor 
    INTO @ID, @Leg_Name, @Op_Name 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     -- For every unprocessed record in temp table check if there is any possible duplicate. 
     -- and insert all possible duplicate records in same table for further processing to find their possible duplicates  
     INSERT INTO #Temp_Employers 
     select ID, Leg_Name, Op_Name, 0 
     from dbo.Name_Table 
     WHERE (Leg_Name = @Leg_Name 
     OR  Op_Name = @Op_Name 
     OR  Leg_Name = @Op_Name 
     OR  Op_Name = @Leg_Name) 
     AND  ID NOT IN (select ID 
          FROM #Temp_Employers) 

     -- Update status of recently processed record to avoid processing again 
     UPDATE #Temp_Employers 
     SET  Status = 1 
     WHERE ID = @ID 

     FETCH NEXT 
     FROM @EmployerCursor 
     INTO @ID, @Leg_Name, @Op_Name 
    END 

    -- close cursor and deallocate memory 
    CLOSE @EmployerCursor 
    DEALLOCATE @EmployerCursor 
END 

select ID, 
     Leg_Name, 
     Op_Name 
from #Temp_Employers 
Order By ID 

DROP TABLE #Temp_Employers 

END 
+0

請包括您爲解決此問題而自行解決的任何嘗試(如果有的話),表明您已做出體面的努力來實現您想要的結果集。如果你還沒有做出自己的嘗試,可以考慮做一些研究,嘗試寫幾個查詢,一旦你有更多的東西要顯示,就返回。要求某人簡單地「給我寫一個確實如此的查詢」的問題可能會被封閉。 – Santi

+0

到目前爲止,您是否會包含用於最佳查詢的代碼? 對此的完整答案取決於您從哪裏開始以及數據的複雜程度。 認識到這一點也很重要,當試圖在數據中查找重複項時,您實際上正在確定重複數據的可能性。 說了上面的話,你可能能夠通過自我加入來描述你所描述的情況。這裏是一個非常粗糙的(完全未經測試,可能需要修復)開始:SELECT * FROM employers.e1 JOIN employers.e2 ON e1.OperatingName = e2.OperatingName UNION(LegalName query) – MER

+0

對不起,我是這個論壇的新手。我試圖通過遞歸CTE來實現這一點,但後來我意識到它將進入無限遞歸。我添加了我的問題以包含代碼 –

回答

0

你可以用兩個自連接來完成這個。我以前DISTINCT是安全的 - 你不需要它你的榜樣,但可能會爲您的實際數據:只要你喜歡

SELECT DISTINCT T2.EMPID, T2.LEGAL_NAME, T.LEGAL_NAME 
FROM TABLE T 
INNER JOIN TABLE T2 ON T.LEGAL_NAME = T2.OPERATING_NAME 
INNER JOIN TABLE T3 ON T2.OPERATING_NAME = T3.OPERATING_NAME 
WHERE T.LEGAL_NAME <> T3.LEGAL_NAME 

重命名和別名表和列。

SQL Fiddle Example

編輯 - 如果你也想記錄中,其中OP名字是從法律的名稱簡直是天壤之別,UNION那些:

SELECT DISTINCT T2.EMPID, T2.LEGAL_NAME, T.LEGAL_NAME 
FROM TABLE T 
INNER JOIN TABLE T2 ON T.LEGAL_NAME = T2.OPERATING_NAME 
INNER JOIN TABLE T3 ON T2.OPERATING_NAME = T3.OPERATING_NAME 
WHERE T.LEGAL_NAME <> T3.LEGAL_NAME 

UNION 

SELECT EMPID, LEGAL_NAME, OP_NAME 
FROM TABLE 
WHERE LEGAL_NAME <> OP_NAME 

SQL Fiddle Example 2

+0

如果我有另一個記錄,它將不起作用:7 | AA | KK –

+0

最終,我需要通過檢查包含所有可能組合的所有名稱來找出所有可能的重複項。 –

+0

@RakeshKumar我不認爲這個記錄應該顯示出來。那麼在這種情況下,您還希望包含的記錄僅包含與合法名稱不同的op名稱?現在邏輯是:顯示記錄,如果它的操作名稱是另一個記錄的合法名稱,那麼也顯示記錄是否是複製的基本記錄(在1 | AA | AA的示例中,它本身是正確的) –