2016-09-14 3 views
0

다음 쿼리를 실행하고 있는데별로 비효율적이며 몇 시간이 걸릴 수 있습니다. 나는 오늘 SQL 두뇌 방구를 가지고 있고 나는이 쿼리를 개선하는 방법을 모른다. 이 몇 가지 널 (NULL) VARCHAR 필드는, 나는 중복 행 (다른 행으로 동일한 값을 포함하는 모든 열)를 식별 할 필요가테이블에서 중복 행을 검색하는 쿼리

select * from transactions x where exists (
    select Coalesce(ColA, ''), 
     Coalesce(ColB, ''), 
     Coalesce(ColC, '') 
    from transactions y 
    where Coalesce(x.ColA, '') = Coalesce(x.ColA, '') and 
     Coalesce(x.ColB, '') = Coalesce(x.ColB, '') and 
     Coalesce(x.ColC, '') = Coalesce(x.ColC, '') 
    group by Coalesce(ColA, ''), 
      Coalesce(ColB, ''), 
      Coalesce(ColC, '') 
    having count(*) > 1 
) 

왜이 실행하는 데 너무 오래 걸립니까? 더 좋은 방법이 있어야합니다.

+3

제거'Coalesce' WHERE 절에서 그들은 불필요 –

+0

테이블에 uniqueid 열이 있습니까? 그렇다면 나는 존재하는 그룹화를 삭제하고 x.uniqueid <> y.uniqueid를 추가합니다. 또한, 당신은 실제로 값을 반환하지 않기 때문에 Select 1이나 다른 상수 값을 사용합니다. 나는 또한 당신의 유착 성 일치에주의를 기울일 것이다. 현재 쓰여지고있는 방식은 ''와 NULL이 일치라고 생각할 것이다. –

답변

0

하위 쿼리 조인을 사용하는 것이 훨씬 빠릅니다. 그것은 10 초

select * from transactions x 
join (
    select Coalesce(ColA, ''), 
     Coalesce(ColB, ''), 
     Coalesce(ColC, '') 
    from transactions 
    group by Coalesce(ColA, ''), 
      Coalesce(ColB, ''), 
      Coalesce(ColC, '') 
    having count(*) > 1 
) dups on 
dups.ColA = x.ColA and 
dups.ColB = x.ColB and 
dups.ColC = x.ColC 

이 쿼리에 대한 중요한 것은 그것이 모두 반환 이다/모든 행뿐 아니라 중복

아래에서 실행 (들)

3

당신은

  1. ColA, ColBColC

필요가 무엇에 복합 인덱스를 넣어

  • 을 unnecesssary 검사를 제거하여이를 개선 할 수있는? 테이블 자체에 가입하는 것은 불필요한 것 같습니다. 간단한 GROUP BY을 사용하지 않는 이유는 무엇입니까? WHERE이 필요하지 않습니다.

    SELECT COALESCE(ColA, '') AS ColA, 
         COALESCE(ColB, '') AS ColB, 
         COALESCE(ColC, '') AS ColC, 
         Count(*) As Cnt 
    FROM transactions t 
    GROUP BY COALESCE(ColA, ''), COALESCE(ColB, ''), COALESCE(ColC, '') 
    HAVING Count(*) > 1 
    
  • 2

    이 방법이 유용합니까?

    null 일 수있는 값을 비교해야하는 경우 ISNULL을 사용할 수 있습니다. 내가 작성한 대부분의 내용은 유용한 데이터 세트를 생성하는 것입니다. 6 열과 10,000 행을 사용하면 1 초 이내에 42 개의 동일한 행을 얻을 수 있습니다. 트리플이 없습니다. 최대 100,000 개의 행을 버렸고 몇 개의 트리플을 포함하여 3,489 개의 중복 행을 확보했습니다. 3 초 걸렸어.

    다음은 텍스트를 사용하는 예입니다. 이 모든 것은 100,000 개의 레코드에서 25 초가 걸렸지 만, 내 타이머는 그 중 4 개가 중복을 찾았 음을 보여 주지만 나머지는 테이블 인구입니다.

    DECLARE @transactions2 TABLE (
         ColA  NVARCHAR(30) 
        , ColB  NVARCHAR(30) 
        , ColC  NVARCHAR(30) 
        , ColD  NVARCHAR(30) 
        , ColE  NVARCHAR(30) 
        , ColF  NVARCHAR(30) 
        ) 
    
        DECLARE @names TABLE (
         ID  INT IDENTITY 
        , Name  NVARCHAR(30) 
        ) 
    
    DECLARE @Counter2  INT = 0 
         , @ColA   NVARCHAR(30) 
         , @ColB   NVARCHAR(30) 
         , @ColC   NVARCHAR(30) 
         , @ColD   NVARCHAR(30) 
         , @ColE   NVARCHAR(30) 
         , @ColF   NVARCHAR(30) 
    
    INSERT INTO @names VALUES 
         ('Anderson, Arthur') 
        , ('Broberg, Bruce') 
        , ('Chan, Charles') 
        , ('Davidson, Darwin') 
        , ('Eggert, Emily') 
        , ('Fox, Francesca') 
        , ('Garbo, Greta') 
        , ('Hollande, Hortense') 
        , ('Iguadolla, Ignacio') 
        , ('Jackson, Jurimbo') 
        , ('Katana, Ken') 
        , ('Lawrence, Larry') 
        , ('McDonald, Michael') 
        , ('Nyugen, Nathan') 
        , ('O''Dell, Oliver') 
        , ('Peterson, Phillip') 
        , ('Quigley, Quentin') 
        , ('Ramallah, Rodolfo') 
        , ('Smith, Samuel') 
        , ('Turner, Theodore') 
        , ('Uno, Umberto') 
        , ('Victor, Victoria') 
        , ('Wallace, William') 
        , ('Xing, Xiopan') 
        , ('Young, Yvette') 
        , ('Zapata, Zorro') 
        , (NULL) 
    
    WHILE @Counter2 < 100000 
        BEGIN 
         SET @Counter2 += 1 
         SET @ColA = (SELECT Name FROM @names WHERE ID = ROUND(RAND()*27 +.5,0)) 
         SET @ColB = (SELECT Name FROM @names WHERE ID = ROUND(RAND()*27 +.5,0)) 
         SET @ColC = (SELECT Name FROM @names WHERE ID = ROUND(RAND()*27 +.5,0)) 
         SET @ColD = (SELECT Name FROM @names WHERE ID = ROUND(RAND()*27 +.5,0)) 
         SET @ColE = (SELECT Name FROM @names WHERE ID = ROUND(RAND()*27 +.5,0)) 
         SET @ColF = (SELECT Name FROM @names WHERE ID = ROUND(RAND()*27 +.5,0)) 
    
         INSERT INTO @transactions2 
          SELECT @ColA, @ColB, @ColC, @ColD, @ColE, @ColD 
        END 
    PRINT CAST(GETDATE() AS DateTime2 (3)) 
    ;WITH Dupe 
        AS (
         SELECT *, ROW_NUMBER() OVER 
           (PARTITION BY ISNULL(ColA,''), ISNULL(ColB,''), ISNULL(ColC,''), ISNULL(ColD,''), ISNULL(ColE,''), ISNULL(ColF,'') 
           ORDER BY ISNULL(ColA,''), ISNULL(ColB,''), ISNULL(ColC,''), ISNULL(ColD,''), ISNULL(ColE,''), ISNULL(ColF,'')) AS rn 
          FROM @transactions2 
         ) 
    
    SELECT * FROM Dupe WHERE rn > 1 ORDER BY rn 
    PRINT CAST(GETDATE() AS DateTime2 (3)) 
    
    -1

    이 한 시간 작업이며, 행의 거대한 숫자를 포함하고보기로 만들 수없는 경우, 아마 당신은 IGNORE_DUP_KEY와 UNIQUE 인덱스가있는 테이블에 그것을 삽입을 선택하도록 선택할 것 선택권.

    +0

    왜 투표가 중단 되었습니까? –

    관련 문제