1

我有一个表,(PROPERTY_ID, GPSTIME, STATION_ID, PROPERTY_TYPE, VALUE)其中 PROPERTY_ID 是主键,STATION_ID 是外键。

该表记录状态变化;每行代表给定时间某个站点的属性值。但是,它的数据是从每个属性都是一列(如(STATION_ID, GPSTIME, PROPERTY1, PROPERTY2, PROPERTY3, ...))的旧表转换而来的。因为通常一次只有一个属性发生了变化,所以我有很多重复项。

我需要删除所有具有相同值的连续行。

例子。旧表包含的值如

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 我的旧表仍然完好无损,所以最好尝试在没有重复项的情况下对其进行转换,而不是在转换后处理重复项。

更新。

澄清我想允许哪些重复项,哪些不允许。

  1. 如果属性更改,然后更改回来,我希望保存所有 3 条记录,即使第一个和最后一个包含相同的 station_id、类型和值。
  2. 如果有多个具有相同 station_id、类型和值的连续(通过 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;
4

2 回答 2

1

可能创建一个新表,使用 GROUP BY 从现有表中进行选择填充。像这样的东西(未经测试,请原谅任何错别字):-

INSERT INTO station_property_new
SELECT station_property_id, station_id, property_type, value 
FROM (SELECT station_property_id, station_id, property_type, value, COUNT(*) FROM station_property GROUP BY station_property_id, station_id, property_type, value) Sub1
于 2012-11-22T12:39:37.010 回答
1

关于链接属性,您不能设置唯一约束以确保站/类型/值列的组合是唯一的。这样,您将无法将其更改为会导致重复的值。

于 2012-11-22T13:07:49.537 回答