我有一个包含(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
该表包含约22百万行。
我目前的方法是使用过程迭代表并删除重复项:
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行的测试表上,它将删除10000个重复项,持续6分钟。有没有办法优化程序?
P.S。我仍然保持旧表的原样,所以也许最好尝试转换它而不需要重复,而不是在转换后处理重复项。
更新
澄清我想要允许哪些重复,哪些不重复。
简而言之,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;
答案 0 :(得分:1)
可能会创建一个新表,使用GROUP BY填充现有表中的select。像这样的东西(没有经过测试,可以解释任何错别字): -
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
答案 1 :(得分:1)
关于chainging属性,您无法设置唯一约束以确保站/类型/值列的组合是唯一的。这样,您将无法将其更改为导致重复的值。