(PROPERTY_ID, GPSTIME, STATION_ID, PROPERTY_TYPE, VALUE)
PROPERTY_ID が主キーで STATION_ID が外部キーのような列を持つテーブルがあります。
このテーブルは、状態の変化を記録します。各行は、特定の時間におけるステーションのプロパティ値を表します。ただし、そのデータは、各プロパティが列 (のような(STATION_ID, GPSTIME, PROPERTY1, PROPERTY2, PROPERTY3, ...)
) であった古いテーブルから変換されました。通常、一度に変更されるプロパティは 1 つだけなので、多くの重複があります。
同じ値を持つ連続するすべての行を削除する必要があります。
例。古いテーブルには次のような値が含まれていました
time stn prop1 prop2
100 7 red large
101 7 red small
102 7 blue small
103 7 red small
変換されたテーブルは
(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
テーブルには約 2200 万行が含まれています。
私の現在のアプローチは、プロシージャを使用してテーブルを反復処理し、重複を削除することです。
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 の重複が削除されます。手順を最適化する方法はありますか?
PS私はまだ古いテーブルをそのまま持っているので、変換後に重複を処理するよりも、重複なしで変換してみる方が良いかもしれません。
アップデート。
どの重複を許可し、どれを許可しないかを明確にするため。
- プロパティが変更されてから元に戻る場合、最初と最後のレコードに同じ station_id、type、および value が含まれていても、3 つのレコードすべてを保存する必要があります。
- 同じ station_id、type、および value を持つ連続した (GPSTIME による) レコードが複数ある場合、最初のレコード (その値の変更を表す) のみを保存する必要があります。
つまり、a -> b -> b -> a -> a
に最適化する必要がありますa -> b -> a
。
解決
@Kickstart が示唆したように、フィルタリングされたデータが入力された新しいテーブルを作成しました。前の行を参照するために、この質問で使用されているものと同様のアプローチを使用しました。
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;