복붙노트

[SQL] 테이블의 한 열을 기준으로 중복 된 값을 제거

SQL

테이블의 한 열을 기준으로 중복 된 값을 제거

내 쿼리 :

SELECT sites.siteName, sites.siteIP, history.date
FROM sites INNER JOIN
     history ON sites.siteName = history.siteName
ORDER BY siteName,date

출력의 첫 부분 :

어떻게적인 siteName 열에서 중복을 제거 할 수 있습니까? 나는 날짜 열을 기준으로 만 업데이트를 떠나고 싶어.

위의 예제 출력에서, I는 행 1, 3, 6, 10해야

해결법

  1. ==============================

    1.윈도우 기능 ROW_NUMBER ()가 편리 할 것입니다 :

    윈도우 기능 ROW_NUMBER ()가 편리 할 것입니다 :

    SELECT s.siteName, s.siteIP, h.date
    FROM sites s INNER JOIN
         (select h.*, row_number() over (partition by siteName order by date desc) as seqnum
          from history h
         ) h
        ON s.siteName = h.siteName and seqnum = 1
    ORDER BY s.siteName, h.date
    
  2. ==============================

    2.귀하의 예제에서 siteIP 열 (즉, 각 사이트는 하나의 siteIP있다) 사이트 이름 컬럼에 의해 결정되는 것을 가정하는 것이 합리적 보인다. 이 실제로 경우라면, 다음으로 그룹을 사용하여 간단한 해결책이있다 :

    귀하의 예제에서 siteIP 열 (즉, 각 사이트는 하나의 siteIP있다) 사이트 이름 컬럼에 의해 결정되는 것을 가정하는 것이 합리적 보인다. 이 실제로 경우라면, 다음으로 그룹을 사용하여 간단한 해결책이있다 :

    select
      sites.siteName,
      sites.siteIP,
      max(history.date)
    from sites
    inner join history on
      sites.siteName=history.siteName
    group by
      sites.siteName,
      sites.siteIP
    order by
      sites.siteName;
    

    내 가정이 정확하지 않은 경우, 그것은 siteIP이 쿼리는 두 번째 열에서 반환 할 당신의 질문에서 명확하지 않다 (입니다 사이트가 여러 siteIP을하는 것이 가능합니다). 다만 어떤 siteIP 경우, 다음 쿼리는 할 것입니다 :

    select
      sites.siteName,
      min(sites.siteIP),
      max(history.date)
    from sites
    inner join history on
      sites.siteName=history.siteName
    group by
      sites.siteName
    order by
      sites.siteName;
    
  3. ==============================

    3.나는이 패턴을 사용하여 이러한 쿼리를 해결할 수 :

    나는이 패턴을 사용하여 이러한 쿼리를 해결할 수 :

    SELECT *
    FROM t
    WHERE t.field=(
      SELECT MAX(t.field) 
      FROM t AS t0 
      WHERE t.group_column1=t0.group_column1
        AND t.group_column2=t0.group_column2 ...)
    

    즉 필드의 값이 최대 값이다가 레코드를 선택할 것입니다. 나는 두 번 가입을 반복 할 필요가 없도록 쿼리에 적용하기 위해 필자는 공통 테이블 표현식을 사용 :

    WITH site_history AS (
      SELECT sites.siteName, sites.siteIP, history.date
      FROM sites
      JOIN history USING (siteName)
    )
    SELECT *
    FROM site_history h
    WHERE date=(
      SELECT MAX(date) 
      FROM site_history h0 
      WHERE h.siteName=h0.siteName)
    ORDER BY siteName
    

    그것은 고유를 위해 우리가 최대 값을 계산하는 경우에만 분야 경우에 작동하는 것이 중요합니다. 귀하의 예제에서 날짜 필드는 IP가 밀리 초마다 여러 번 변경할 수없는 경우 각적인 siteName에 대해 고유해야합니다. 내 경험에 의하면 이것은 일반적으로 그렇지 않으면 당신은 최신 어쨌든 어떤 기록 모르는 경우입니다. 역사 테이블 (사이트, 날짜)에 대한 고유 인덱스가있는 경우,이 쿼리는 인덱스가 단지 첫 번째 항목이 사용할 수있는 기록 테이블 스캔에 스캔 범위, 매우 빠릅니다.

  4. from https://stackoverflow.com/questions/17507887/eliminating-duplicate-values-based-on-only-one-column-of-the-table by cc-by-sa and MIT license