2016-08-15 3 views
3

"보다 완전한"중복을 선택하는 SQL 쿼리를 작성하려고합니다. 예를 들어 우리 테이블에 Name, Phone, Email, CompanyId 및 Both라는 두 개의 필드가있는 경우 & CompanyId는 두 개의 레코드가 같지만 그 중 하나에는 Phone 및/또는 Email이 있고 다른 레코드에는이 두 필드가 비어 있습니다 , 완료된 레코드 만 레코드 세트에서 사용할 수 있습니다."보다 완전한"중복 레코드를 선택하는 쿼리

나는 쿼리가 다운 된 줄 알았지 만 "더 완벽한"레코드가 존재하지 않는다면 그 레코드는 완전히 삭제되거나 레코드 세트에 중복 된 채로 남아있게됩니다 (쿼리 수정 방법에 따라 다름). 데이터 손실/복제가 발생하지 않는 더 나은 방법이 있는지 확신 할 수 없습니다. 지금 내가 생각할 수있는 것은 UNION에 더 많은 다른 쿼리가 있지만 더 나은 방법이 있어야한다고 생각합니다. 나는 원시 데이터를 얻을 수있는 CTE를 사용하고 여기에 내가 중복 제거를 조작 할 노력하고있어 무엇을 해요 : 몇 쿼리를 unioning하는 것은 큰 문제가 아니다이 필요한 것 인 경우

;WITH Contacts AS ( 
    -- LONG QUERY HERE THAT UNIONS NECESSARY Tables & XML Columns AND returns a recordset with Name, Email, Phone, and ClientId 
) 
SELECT u.* FROM Contacts u 
INNER JOIN (
    SELECT Name, ClientId, Count(*) AS ct FROM Contacts 
    GROUP BY Name, ClientId 
    HAVING COUNT(*) > 1 
) AS g 
ON u.Name = g.Name AND u.ClientId = g.ClientId 
WHERE Phone IS NOT NULL AND Email IS NOT NULL 
UNION 
SELECT u.* FROM Contacts u 
INNER JOIN (
    SELECT Name, ClientId, Count(*) AS ct FROM Contacts 
    GROUP BY Name, ClientId 
    HAVING COUNT(*) = 1 
) AS h 
ON u.Name = h.Name AND u.ClientId = h.ClientId 

을 , 아마 이것을 처리하는 더 좋은 방법이있는 것처럼 보입니다. 어떤 제안?

편집 : 샘플 데이터

쿼리 후
Name  | Phone   | Email  | ClientId 
------------------------------------------------------ 
Person1 | NULL   | NULL   | 42 
Person1 | 555-555-5555 | [email protected] | 42 
Person2 | NULL   | NULL   | 21 
Person2 | NULL   | NULL   | 21 
Person3 | 555-555-5555 | NULL   | 79 
Person3 | NULL   | NULL   | 79 
Person4 | 555-555-5555 | NULL   | 49 
Person4 | NULL   | [email protected] | 49 
Person5 | 555-555-5555 | NULL   | 91 
Person5 | 555-555-5555 | [email protected] | 91 
Person6 | 555-555-5555 | NULL   | 91 

반환 데이터 집합 -

Name  | Phone   | Email  | ClientId 
------------------------------------------------------ 
Person1 | 555-555-5555 | [email protected] | 42 
Person2 | NULL   | NULL   | 21 
Person3 | 555-555-5555 | NULL   | 79 
Person4 | 555-555-5555 | [email protected] | 49 
Person5 | 555-555-5555 | [email protected] | 91 
Person6 | 555-555-5555 | NULL   | 91 

Person4 데이터의 병합은 이상적인 상황이지만, 반드시 대답 내가 찾고 있어요 없습니다 이 질문에. 이름 또는 이메일이 채워지는 한 가지 상황에서 데이터가 손실되지 않는 한 중복 된 데이터는 괜찮습니다.

+0

당신이 데이터를 내가 실제 데이터를 표시 할 수 없습니다 – TheGameiswar

+0

@TheGameiswar을 일부 실제 데이터를 보여 예상시겠습니까,하지만 난 내게 줄까지 약간의 조롱 것 몇 분. – JNYRanger

+0

그게 도움이 될거야, 나는 실제 데이터를 쓸 때 샘플 데이터를 의미한다 – TheGameiswar

답변

2

이 .. 확실히 작동합니다

select 
name,max(phone),max(email),clientid 
from 
Table t 
group by name,clientid 
+0

간단하고 지금까지 발견 한 모든 시나리오에 사용할 수 있습니다! 나는이 문제를 지나치게 생각하고 있음을 알았다. 감사! – JNYRanger

+0

@JNYRanger : 나도 – TheGameiswar

+0

:)하지만 왜'max()'입니까? – Serg

-1

특정 열을 기반으로 중복 선택이

WITH CT AS(
      SELECT Name, Phone, Email, CompanyId, 
    --This part determines duplicates by field 
       RN = ROW_NUMBER()OVER(PARTITION BY Name,CompanyId ORDER BY Name) 
      FROM Contacts 
     ) 
     select FROM CT WHERE email <> '' and phone <> '' 

을 시도 여기

ROW_NUMBER()OVER(PARTITION BY {column1}, {column2}..... 
2

이 모든 name은 "최고"행을 반환 해. 가장 좋음은 추가 열의 최대 수 (Mail, Phone)가 널이 아님을 의미합니다.

select top(1) with ties * 
from Contact 
order by row_number() over (partition by Name order by 
     case when Phone is null then 0 else 1 end + case when Email is null then 0 else 1 end desc) 
+0

4 행을 병합해야합니다 .Person4 – TheGameiswar

+0

병합 규칙에 대해 잘 모르겠습니다. 예를 들어 널 입력 가능 열'Skype '이 두 개 있고'Person4' 행의 값이'abc' 및'xyz'라고 가정합니다. 병합 된 행에 어떤 Skype가 있어야합니까? – Serg

+0

@Serg 이것은 좋은 지적이지만 데이터에서는 결코 발생하지 않습니다. 데이터에는 중복 레코드가 있고 전자 메일과 전화가 모두 채워지는 시나리오는 없습니다 (동일한 값이 아님). 그것은 아무것도 가지고 있지 않은 것, 이메일 만, 전화 만, 또는 완전히 채워져있는 속임수 일 것입니다. 전화 또는 전자 메일의 경우에만 두 개의 중복이 채워지면 복제본에 항상 동일한 값을 갖게됩니다.운이 좋으면 데이터가 엉망이지만 조작하기에는별로 좋지 않습니다. – JNYRanger