2017-03-29 14 views
1

SSN、姓およびDOBの最後の4つに基づいて、データベース内の潜在的重複顧客を特定しようとしています。私が書いたストアドプロシージャは潜在的な重複を特定しますが、それらは1つの行にリストされています - 報告理由のために別々の行に分割しようとしています。異なる行に重複した潜在的な複製

私のT-SQLは次のようになります。

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と二人のユーザーを持っています同じ姓と同じDOBですが、最初の名前は異なります。

これらの2つのレコードを別々の行に表示するにはどうすればよいですか?理想的には、私は見たい:

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 

しかし、私は同じテーブルに参加するときにこれを達成することができますか分かりません。提案?

問題の2つのテーブルを作成し、サンプルデータを挿入するスクリプトにリンクしています。うまくいけば受け入れられる:SQL Script

+0

テーブル定義とサンプルデータを提供できますか –

+0

確かに、基礎となるテーブルまたは結果セットテーブル定義のテーブル定義が必要ですか? – MISNole

+0

問題を再現し、解決策を出すのに十分なだけのすべての列は必要ない –

答えて

1

これは「ピボット解除」と呼ばれます。 UNPIVOT演算子を使用できますが、CROSS APPLY ... VALUESを使用することをお勧めします。

詳細を見ることなくクエリをCTEにラップし、CROSS APPLYを使用して各行を2つに分割します。ところで

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は、私が一度も使ったことのないものや、使い方が分かっていないものの1つです。しかし、これは速く実行され、私が望んでいたようにデータはよく見えます。そして、ROW_NUMBERまでは、SSNがいつリセットされるのかを私が見やすくしていると思います。ありがとう! – MISNole

+0

私は答えを高く評価していますVlad - 私はあなたが多くの担当者を獲得したいと思えば、これは私が質問をして別の質問を投稿する必要がある場所に近いと思います:http://stackoverflow.com/questions/43132297/cross-apply-creating-追加のレコード – MISNole

+0

@MISNole、申し訳ありませんが、データの消去/重複の検索は、通常、面倒で困難です。私はすべてのケースをカバーする1つのクエリがあるとは思わない。 –

関連する問題