2017-03-29 2 views
1

SSN, 성 및 DOB의 마지막 4 개를 기준으로 데이터베이스에서 잠재적 인 중복 고객을 식별하려고합니다. 필자가 작성한 저장 프로 시저는 잠재적 중복을 식별하지만 한 행에 나열합니다.보고 이유에 따라 별도의 행으로 분할하려고합니다.다른 행에 중복 된 잠재적 인 중복

DECLARE 
@StartDate DATE = '1/1/2017', 
@EndDate DATE = '3/1/2017'; 

SELECT DENSE_RANK() OVER (ORDER BY c.socialSecurityNumber) AS [SSNRanking] , 
    ROW_NUMBER() OVER (PARTITION BY c.socialSecurityNumber ORDER BY c.socialSecurityNumber) AS [RowNumb] , 
    c.socialSecurityNumber AS [SSN], 
    c.id AS [CustomerID] , 
    c.firstName AS [FirstName] ,  
    c.lastName AS [lastName] , 
    c.birthDate [birthdate] , 
    c.createDate AS [CreateDate] , 
    c2.socialSecurityNumber AS [DupSSN] , 
    c2.id AS [DupCustomerID] , 
    c2.firstName AS [DupFirstName] , 
    c2.lastName AS [DupLastName] , 
    c2.birthDate AS [DupBirthDate] , 
    c2.createDate AS [DupCreateDate] 
FROM dbo.Customers AS [c] 
    INNER JOIN dbo.Customers AS [c2] ON (SUBSTRING(c.socialSecurityNumber,6,4) = SUBSTRING(c2.socialSecurityNumber,6,4) AND c.birthDate = c2.birthDate AND c.lastName = c2.lastName AND c.id <> c2.id) 
    LEFT JOIN dbo.CustomerAddresses AS [CA] ON c.id = CA.customerID    
    LEFT OUTER JOIN dbo.Common_Orders AS [co] ON co.customerID = c.id 
WHERE 
    c.customerStatusTypeID <> 'M' 
    AND C2.customerStatusTypeID <> 'M' 
    AND c.mergedTo IS NULL 
    AND c2.mergedTo IS NULL 
    AND CAST(co.orderDate AS DATE) >= @StartDate 
    AND CAST(co.orderDate AS DATE) <= @EndDate 
    AND c.id = 1234439 
GROUP BY c.socialSecurityNumber , 
    c.id , 
    c.firstName , 
    c.lastName , 
    c.birthDate ,  
    c.createDate , 
    c2.socialSecurityNumber , 
    c2.id , 
    c2.firstName ,   
    c2.lastName , 
    c2.birthDate , 
    c2.createDate 
ORDER BY CAST(c.socialSecurityNumber AS INT) ASC; 

그리고 내 데이터 세트는 다음과 같습니다 :이 특정 인스턴스에서

SSNRanking RowNumb SSN  CustomerID FirstName lastName birthdate CreateDate DupSSN  DupCustomerID DupFirstName DupLastName DupBirthDate DupCreateDate 
1   1  000009915 1234439  GREG  GARRETT 1900-01-01 2014-02-25 000009915 1166084  ADAM   GARRETT  1900-01-01 2013-08-29 

, 나는 SSN 같은 마지막 4 두 명의 사용자가, 같은

내 T-SQL 보인다 동일한 성 및 동일한 DOB - 그러나 다른 이름.

어떻게이 두 레코드를 별도의 줄에 표시 할 수 있습니까? 이상적으로, 나는보고 싶다 :

SSNRanking RowNumb SSN  CustomerID FirstName lastName birthdate CreateDate 
1   1  000009915 1234439  GREG  GARRETT 1900-01-01 2014-02-25 
1   2  000009915 1166084  ADAM  GARRETT 1900-01-01 2013-08-29 

그러나 나는 이것이 동일한 테이블에 가입 할 때 어떻게 성취 할 수 있는지 잘 모르겠다. 제안?

문제의 두 테이블을 만들고 샘플 데이터를 삽입하는 스크립트에 연결하고 있습니다. 잘하면 받아 들일 만합니다 : SQL Script

+0

테이블 정의 및 샘플 데이터를 제공 할 수 있습니까? –

+0

확실히 - 기본 테이블 또는 결과 세트 테이블 정의 작업에 대한 테이블 정의가 필요합니까? – MISNole

+0

기본 테이블은 있지만 문제를 복제하고 해결책을 제시하기에 충분할만큼 모든 열을 필요가 없습니다. –

답변

1

이것을 "피벗 해제"라고합니다. UNPIVOT 연산자를 사용할 수 있지만 CROSS APPLY ... VALUES을 사용하는 것이 좋습니다.

자세한 내용을 보지 않고 CTE에 검색어를 포장하고 CROSS APPLY을 사용하여 각 행을 두 개로 나눕니다. 그런데

DECLARE 
@StartDate DATE = '1/1/2017', 
@EndDate DATE = '3/1/2017'; 

WITH 
CTE 
AS 
(
    SELECT 
     DENSE_RANK() OVER (ORDER BY c.socialSecurityNumber) AS [SSNRanking] , 
     ROW_NUMBER() OVER (PARTITION BY c.socialSecurityNumber ORDER BY c.socialSecurityNumber) AS [RowNumb] , 
     c.socialSecurityNumber AS [SSN], 
     c.id AS [CustomerID] , 
     c.firstName AS [FirstName] ,  
     c.lastName AS [lastName] , 
     c.birthDate [birthdate] , 
     c.createDate AS [CreateDate] , 
     c2.socialSecurityNumber AS [DupSSN] , 
     c2.id AS [DupCustomerID] , 
     c2.firstName AS [DupFirstName] , 
     c2.lastName AS [DupLastName] , 
     c2.birthDate AS [DupBirthDate] , 
     c2.createDate AS [DupCreateDate] 
    FROM  
     dbo.Customers AS [c] 
     INNER JOIN dbo.Customers AS [c2] ON (SUBSTRING(c.socialSecurityNumber,6,4) = SUBSTRING(c2.socialSecurityNumber,6,4) AND c.birthDate = c2.birthDate AND c.lastName = c2.lastName AND c.id <> c2.id) 
     LEFT JOIN dbo.CustomerAddresses AS [CA] ON c.id = CA.customerID    
     LEFT JOIN dbo.Common_Orders AS [co] ON co.customerID = c.id 
    WHERE 
     c.customerStatusTypeID <> 'M' 
     AND C2.customerStatusTypeID <> 'M' 
     AND c.mergedTo IS NULL 
     AND c2.mergedTo IS NULL 
     AND CAST(co.orderDate AS DATE) >= @StartDate 
     AND CAST(co.orderDate AS DATE) <= @EndDate 
     AND c.id = 1234439 
    GROUP BY 
     c.socialSecurityNumber , 
     c.id , 
     c.firstName , 
     c.lastName , 
     c.birthDate ,  
     c.createDate , 
     c2.socialSecurityNumber , 
     c2.id , 
     c2.firstName ,   
     c2.lastName , 
     c2.birthDate , 
     c2.createDate 
) 
SELECT 
    CA.SSNRanking 
    ,CA.RowNumb 
    ,CA.SSN 
    ,CA.CustomerID 
    ,CA.FirstName 
    ,CA.lastName 
    ,CA.birthdate 
    ,CA.CreateDate 
FROM 
    CTE 
    CROSS APPLY 
    (
     VALUES 
     (CTE.SSNRanking, CTE.RowNumb, CTE.SSN, CTE.CustomerID, CTE.FirstName, CTE.lastName, CTE.birthdate, CTE.CreateDate), 
     (CTE.SSNRanking, CTE.RowNumb, CTE.DupSSN, CTE.DupCustomerID, CTE.DupFirstName, CTE.DuplastName, CTE.Dupbirthdate, CTE.DupCreateDate) 
    ) AS CA(SSNRanking, RowNumb, SSN, CustomerID, FirstName, lastName, birthdate, CreateDate) 
ORDER BY CAST(CA.SSN AS INT) ASC; 

,

ROW_NUMBER() OVER (PARTITION BY ColumnA ORDER BY ColumnA) 

같은 열을 기준으로하면 분할 감각과 주문을하지 않습니다. 나는 당신이 그곳에서 성취하고자하는 것을 확신하지 못합니다.

+1

니스 - 나는이 해결책을 좋아한다. CROSS APPLY는 내가 사용한 적이 없거나 실제로 사용법을 알고있는 것들 중 하나입니다. 그러나 이것은 빠르게 진행되고 데이터는 내가 바라는대로 좋아 보인다. 그리고 ROW_NUMBER까지는 SSN이 리셋되는 것을 더 쉽게 볼 수 있다고 생각합니다. 감사! – MISNole

+0

나는 당신이 더 많은 담당자를 얻는 것을 느끼는 경우에 나는 Vlad를 응답을 평가한다 - 나는 이것이 질문을 필요로하고 다른 질문을 배치 한 곳에 거의다는 것을 믿는다 : http://stackoverflow.com/questions/43132297/cross-apply-creating- 추가 기록 – MISNole

+0

@MISNole, 죄송합니다, 데이터 정리/중복 발견은 일반적으로 복잡하고 어렵습니다. 나는 모든 경우를 다루는 하나의 질의가있을 수 있다고 생각하지 않는다. –