2014-07-10 7 views
0

중복을 제거하기 위해 쿼리 작성을 도와 주시겠습니까? 아래 참조 결과를 보겠습니다. 내 상태가 (수동으로) 추가 된 항목이 있습니다. 범주는 레코드가 중복 된 레코드인지 여부를 결정하는 범주입니다. 이 경우 우리의 주요 초점은 취소입니다. 회원의 경우 회원 자격 취소 후 회원 자격 회복이 Y007입니다. 중복으로 간주되지 않습니다. 그러나 회원이 여러 건의 취소를 한 경우 중복으로 간주됩니다. 중복 횟수를 계산하면 둘 다 계산되므로 잘못된 결과가 나타납니다. 우리는 회원을 한번 카운트해야합니다. 취소는 사용자 또는 사용자 1이 수행 할 수 있으며 user1은 둘 이상의 취소를 수행 할 수 있습니다. 중복 된 내용이 표시되지 않도록 쿼리 작성에 도움을주십시오. 해당 멤버에 대해 하나 개의 기록이 개 기록은 모두 중복중복 레코드 제거

CreateYear MonthDay  Category   Member Status 
2014 July 1 Cancellation by User Y0007 
2014 July 1 Reinstatement by User Y0007 not duplicate 
2014 July 2 Cancellation by User Y0007 
2014 July 2 Reinstatement by User Y0007 
2014 July 1 Cancellation by User O0031 not duplicate 
2014 July 8 Reinstatement by User O0031 
2014 July 1 Cancellation by User O0135 not duplicate 
2014 July 8 Reinstatement by User O0135 
2014 July 3 Cancellation by User P0422 duplicate 
2014 July 4 Cancellation by User2 P0422 
2014 July 4 Cancellation by User E3488 not duplicate 
2014 July 8 Reinstatement by User E3488 
+4

어떤 DBMS를 사용하고 있습니까? 포스트그레스? 신탁? –

+0

sql server 2012를 사용 중입니다 – user1538257

+0

'제거'라고 말하면 레코드를 삭제한다고 말하거나 단순히 원하는 쿼리의 결과로 포함시키지 마십시오. – Edper

답변

0

전략

에 의해 그룹을 사용할 수 있습니다. 적절한 select 문을 작성할 수 있으면 delete 문으로 쉽게 변환 할 수 있습니다. 이제 select 문은 날짜를 비교해야하기 때문에 약간 까다 롭습니다. 그러나 날짜는 세 개의 열로 나뉘며 월은 숫자로 저장되지 않습니다. 그러나 세 개의 열을 연결하여 날짜로 형변환하면 날짜 값을 비교하고 연속으로 여러 번 발생한 취소를 찾을 수 있습니다.

쿼리이 쿼리는 조금 강렬한 보이지만,의 그것을 통해 이야기하자

Select * 
From testtable t 
Where category = 'Cancellation' 
and exists (Select 1 
      From testtable t2 
      Where t2.category = t.category 
      and  t2.Member = t.Member 
      and  Cast(t2.CreateMonth + ' '+ cast(t2.CreateDay as varchar(2)) + ' ' + Cast(t2.CreateYear as varchar(4)) as date) > 
        Cast(t.CreateMonth + ' '+ cast(t.CreateDay as varchar(2)) + ' ' + Cast(t.CreateYear as varchar(4)) as date) 
      and not exists (Select 1 
          From testtable t3 
          Where t3.category = 'Reinstatement' 
          and  t3.Member = t.Member 
          and  Cast(t3.CreateMonth + ' '+ cast(t3.CreateDay as varchar(2)) + ' ' + Cast(t3.CreateYear as varchar(4)) as date) >= 
            Cast(t.CreateMonth + ' '+ cast(t.CreateDay as varchar(2)) + ' ' + Cast(t.CreateYear as varchar(4)) as date) 
          and  Cast(t2.CreateMonth + ' '+ cast(t2.CreateDay as varchar(2)) + ' ' + Cast(t2.CreateYear as varchar(4)) as date) >= 
            Cast(t3.CreateMonth + ' '+ cast(t3.CreateDay as varchar(2)) + ' ' + Cast(t3.CreateYear as varchar(4)) as date) 
          ) 
      ) 

Explaination. 먼저 별칭을 제외하고는 처음에는이 모든 것을 select * From testtable t으로 보았을 것입니다. 나는이 특정 인스턴스를 testtable Where category = 'Cancellation'이라고 지었다. 필자는 본질적으로 닉네임 t를 부여했기 때문에 이름 대신 테이블을 참조하는 대신 (같은 테이블을 세 번 사용하기 때문에 혼란스러워하기 때문에) t로 참조 할 수 있습니다.

지금은 exists입니다. 이 구문은 사용자가 본 것과 다른 구문 일 수도 있고 아닐 수도 있습니다. Exists는 괄호 안에 그 뒤에 오는 것이 있으면 true를 반환하고 괄호 안에 아무 것도없는 경우 false를 반환합니다. 나는 이것을 사용하여 testtable에서 우리가보고있는 취소보다 새로운 다른 레코드를 확인하고 또한 취소합니다.

이것은 날짜가 들어오는 곳입니다. 월과 일이 우리가보고있는 취소보다 큰 다른 취소가있는 경우에만 알 수 있습니다. 회원 P0422의 경우 7 월 3 일에 취소가 중복되었는지 여부를 결정할 때 7 월 4 일에 취소를 찾고 싶습니다.

서브 선택에서 나는 not exists을 사용 중입니다. 우리가 점검해야 할 마지막 사항은 두 취소 사이에 복직이있는 경우입니다.존재하는 경우 취소를 무시하고 다음 행을 확인하기 위해 계속 진행합니다. 날짜로 See the query in action

캐스트에 깊이 레코드의 일이 무엇인지 알아 내기 위해이 쿼리에 Cast(t2.CreateMonth + ' '+ cast(t2.CreateDay as varchar(2)) + ' ' + Cast(t2.CreateYear as varchar(4)) as date) 여러 번 같은

내가 사용한 구문을 찾습니다. 취소 (또는 복직) 날짜가 세 개의 열로 나뉘었기 때문에이 작업을 수행했습니다.

다음 레코드에 대해 무엇을하는지 보도록하겠습니다.

먼저

CreateYear MonthDay  Category   Member Status 
2014 July 1 Cancellation by User Y0007 

은 연결이다. t2.CreateMonth + ' '+ cast(t2.CreateDay as varchar(2)) + ' ' + Cast(t2.CreateYear as varchar(4))이 부분은 각 열의 다양한 정보를 가져 와서 모두 연결합니다. 1 년과 1 일은 int이며 varchars가 아니므로 먼저 varchars로 전환했습니다. 이 줄의 결과는 July 1 2014입니다.

그런 다음 우리는 Cast (... as date)입니다. 전송을 사용하면 정보를 가져 와서 다른 데이터 유형으로 만들 수 있습니다. 따라서 이것은 sql에게 문자열 대신에 날짜 인 것처럼 July 1 2014을 보게합니다. 이 모든 것은 날짜를 비교할 수 있도록 수행되었습니다. Sql은 어떤 날짜가 다른 날짜보다 최근 날짜인지 알려주는 바입니다. 그래서이 값을 변환 한 것입니다. 이 작업을 수행하는 대신, 날짜의 각 부분을 개별적으로 비교할 수 있지만, 어느 쪽이든 여전히 많은 작업이 있습니다.

삭제합시다!

중복 된 모든 행을 찾았으므로 정말 쉽게 삭제할 수 있도록 검색어를 변경할 수 있습니다.

Delete t 
From testtable t 
Where category = 'Cancellation' 
and exists (Select 1 
      From testtable t2 
      Where t2.category = t.category 
      and  t2.Member = t.Member 
      and  Cast(t2.CreateMonth + ' '+ cast(t2.CreateDay as varchar(2)) + ' ' + Cast(t2.CreateYear as varchar(4)) as date) > 
        Cast(t.CreateMonth + ' '+ cast(t.CreateDay as varchar(2)) + ' ' + Cast(t.CreateYear as varchar(4)) as date) 
      and not exists (Select 1 
          From testtable t3 
          Where t3.category = 'Reinstatement' 
          and  t3.Member = t.Member 
          and  Cast(t3.CreateMonth + ' '+ cast(t3.CreateDay as varchar(2)) + ' ' + Cast(t3.CreateYear as varchar(4)) as date) >= 
            Cast(t.CreateMonth + ' '+ cast(t.CreateDay as varchar(2)) + ' ' + Cast(t.CreateYear as varchar(4)) as date) 
          and  Cast(t2.CreateMonth + ' '+ cast(t2.CreateDay as varchar(2)) + ' ' + Cast(t2.CreateYear as varchar(4)) as date) >= 
            Cast(t3.CreateMonth + ' '+ cast(t3.CreateDay as varchar(2)) + ' ' + Cast(t3.CreateYear as varchar(4)) as date) 
          ) 
      ) 
+0

안녕하세요, Jenn 당신의 도움에 너무 감사드립니다. 사용했던 논리가 많이 도움이되었습니다. 십자가를 사용하여 여러 가지 방법으로 시도해 보았습니다. 적용 및 내부 조인. 오류가 발생하더라도 문제를 해결하는 데 어려움이 없었던 방식으로 이것을 아주 잘 설명했습니다. 좋은 일을 계속 지켜라. 이제 모든 미소가 지어진다. 많이 soooo 고마워. – user1538257

+0

@ user1538257 좋아요, 듣고 기쁩니다! 내 대답을 받아 주시겠습니까? – Jenn

+0

@ user1538257 각 답변 옆에는 작은 확인란이 있습니다. 그 대답이 '받아들이는 것이 도움이된다는 것을 보여줄 수 있습니다. 또한 질문에 더 많은 것이 있으면 새로운 질문을하는 것이 좋습니다. 새로운 대답을 얻는 것이 훨씬 쉬울 것입니다. – Jenn

0

과 같이 뭔가를해야만처럼 쓸 수 없습니다 : -

DELETE FROM TABLE_NAME 
WHERE member NOT IN (SELECT MAX(member) FROM TABLE_NAME 
         GROUP BY CreateYear, MonthDay, Category, Member, Status); 

나는이 문제를 해결 줘야 바랍니다.

+0

안녕하세요 Ankit,이 작업은 몇 분 전에 시도한 것을 볼 수 있습니다. 당신은 또한 중복을 제외하기 위해 카테고리 "cancelations"을보고 있다고 생각해야합니다. 예를 들어 멤버 "E3488"이 둘 이상의 취소로 인해 중복 된 것으로 간주합니다. 동시에 우리는 중복으로 간주되지 않으며 둘 이상의 취소를 가지고있는 회원 "Y0007"도 있습니다. 그래서 우리가 취소 회원의 최대를 보면이 두 가지가 검색 될 것입니다. 즉 잘못된 것입니다. 단 하나의 회원 취소만을 검색하려고합니다. – user1538257

+0

글쎄, 나는 이것을 결코 시도하지 않았다. 그래서 나는 단지 당신에게 같은 것을해야한다는 암시를주었습니다. 그러나 당신을 그렇게 많이 돕지 못해서 유감입니다. –

+0

그래도 고맙습니다. – user1538257

-1

당신은 중복 제거의 경우에만 중복을 선택하는 몇 가지 코드를 작성하여 시작하자하기 위해

Select Create,Year,MonthDay,Category , Member,Status 
From tblname 
Group By Category 
+0

코드가하는 일에 대한 설명과 질문에 대한 대답을 함께 적어주십시오. 코드 스 니펫을 답으로 얻는다면 그 코드 스 니펫으로 무엇을해야할지 모를 수 있습니다. 답은 OP와 미래 방문자에게 문제를 디버그하고 수정하는 방법에 대한 지침을 제공해야합니다. 코드 뒤에있는 아이디어가 무엇인지 지적하면 문제를 이해하고 솔루션을 적용하거나 수정하는 데 큰 도움이됩니다. – Palec

0
;with TempCte as (Select CreateYear,MonthDay,Category,Member, MemberCount =ROW_NUMBER() 
        over(PARTITION By CreateYear, MonthDay, Category, Member, Status Order By CreateYear) 
        From TableName) 

    Delete TempCte 
    Where MemberCount >1 
+0

Hi humpty 안녕하세요, 각 코드 라인이 무엇을했는지에 대해 설명해주십시오. – user1538257