(PROPERTY_ID, GPSTIME, STATION_ID, PROPERTY_TYPE, VALUE)
과 같은 열이있는 테이블이 있습니다. 여기서 PROPERTY_ID는 기본 키이고 STATION_ID는 외래 키입니다.MySQL에서 연속 된 중복 행을 제거하는 효율적인 방법
이 테이블은 상태 변경을 기록합니다. 각 행은 주어진 시간에 일부 스테이션의 속성 값을 나타냅니다. 그러나 각 속성이 열 (예 : (STATION_ID, GPSTIME, PROPERTY1, PROPERTY2, PROPERTY3, ...)
) 인 이전 테이블에서 데이터가 변환되었습니다. 일반적으로 한 번에 하나의 속성 만 변경되었으므로 중복 된 항목이 많습니다.
모두 연속적인 행을 동일한 값으로 제거해야합니다.
예. 이전 테이블은 변환 표는
(order by time,type) (order by type,time)
time stn type value time stn type value
100 7 1 red 100 7 1 red
100 7 2 large 101 7 1 red
101 7 1 red 102 7 1 blue
101 7 2 small 103 7 1 red
102 7 1 blue 100 7 2 large
102 7 2 small 101 7 2 small
103 7 1 red 102 7 2 small
103 7 2 small 103 7 2 small
이
time stn type value
100 7 1 red
100 7 2 large
101 7 2 small
102 7 1 blue
103 7 1 red
표는 약 22 만명 행이 포함로 변경해야합니다입니다
time stn prop1 prop2
100 7 red large
101 7 red small
102 7 blue small
103 7 red small
같은 값이 포함되어 있습니다.
내 현재의 접근 방식은 중복을 테이블을 반복하고 제거하는 절차를 사용하는 것입니다
BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE id INT;
DECLARE psid,nsid INT DEFAULT null;
DECLARE ptype,ntype INT DEFAULT null;
DECLARE pvalue,nvalue VARCHAR(50) DEFAULT null;
DECLARE cur CURSOR FOR
SELECT station_property_id,station_id,property_type,value
FROM station_property
ORDER BY station_id,property_type,gpstime;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN cur;
read_loop: LOOP
FETCH cur INTO id,nsid,ntype,nvalue;
IF done THEN
LEAVE read_loop;
END IF;
IF (psid = nsid and ptype = ntype and pvalue = nvalue) THEN
delete from station_property where station_property_id=id;
END IF;
SET psid = nsid;
SET ptype = ntype;
SET pvalue = nvalue;
END LOOP;
CLOSE cur;
END
그러나, 그것은 너무 느립니다. 20000 개의 행이있는 테스트 테이블에서 6 분 동안 10000 개의 중복을 제거합니다. 절차를 최적화하는 방법이 있습니까?
P. 나는 여전히 내 오래된 테이블을 그대로 가지고 있기 때문에 변환 후에 중복을 다루지 않고 복제없이 변환하는 것이 더 나을지도 모른다.
업데이트.
허용하고 싶은 복제본을 명확히하기 위해.
- 속성이 변경된 경우 다시 변경됩니다. 첫 번째와 마지막 station_id, type 및 value가 같지만 3 개의 레코드가 모두 저장되기를 원합니다.
- station_id, type 및 value가 동일한 여러 GPSTIME 레코드가있는 경우 첫 번째 레코드 (해당 값의 변경을 나타내는) 만 저장하면됩니다.
즉, a -> b -> b -> a -> a
은 a -> b -> a
으로 최적화되어야합니다.
솔루션
@Kickstart가 제안한 것처럼, 내가 필터링 된 데이터로 채워 새 테이블을 만들었습니다. 이전 행을 참조하려면 this question에 사용 된 것과 비슷한 접근 방식을 사용했습니다.
rename table station_property to station_property_old;
create table station_property like station_property_old;
set @lastsid=-1;
set @lasttype=-1;
set @lastvalue='';
INSERT INTO station_property(station_id,gpstime,property_type,value)
select newsid as station_id,gpstime,newtype as type,newvalue as value from
-- this subquery adds columns with previous values
(select station_property_id,gpstime,@lastsid as lastsid,@lastsid:=station_id as newsid,
@lasttype as lasttype,@lasttype:=property_type as newtype,
@lastvalue as lastvalue,@lastvalue:=value as newvalue
from station_property_old
order by newsid,newtype,gpstime) sub
-- we filter the data, removing unnecessary duplicates
where lastvalue != newvalue or lastsid != newsid or lasttype != newtype;
drop table station_property_old;
결과 (중복되지 않은) 데이터 세트에서 '103 7 1 red'가 나타나는 이유는 무엇입니까? –
@BrankoDimitrijevic 예제에 데이터를 추가했습니다. 시간 = 102에서 prop1이 "red"에서 "blue"로 변경되었습니다. 시간 = 103 prop1이 다시 변경되었습니다. 두 가지 변경 사항을 모두 테이블에 반영하고 싶습니다. 내가 원하지 않는 것은 큰 테이블을 "폭발"시켰을 때 추가 된 '103 7 2 small'과 같은 변경 사항을 나타내지 않는 레코드입니다. – aimozg
@BrankoDimitrijevic는'(type, time)'에 의해 정렬 된 테이블을 보았습니다. 행을 삭제해야하는 것이 더 명확합니다. – aimozg