我有一个MyISAM组织和个人之间的关系表。每条记录都有一个开始和结束日期。这些记录是在处理大型文本文件时添加的,因此我不会进行大量处理和清理,因为它们是为了加快文本解析而添加的。但是,某些记录是冗余的或可能是多余的,因为它们包含重叠的日期范围。
例如,我可以拥有以下内容:
aff_id aff_e1_id aff_e1_type aff_e2_id aff_e2_type aff_start aff_end
------ --------- ----------- --------- ----------- ----------- ----------
01 172 org 131 indiv 1997-01-22 1998-03-31
02 172 org 131 indiv 1997-01-22 1999-04-03
03 100 org 127 indiv 1995-01-02 2000-01-05
04 100 org 127 indiv 1994-01-24 1999-03-04
我想要做的是合并冗余关系的记录并修改日期范围以包含任何重叠。例如,分别可以合并前两个和最后两个记录,并修改日期以包括两个日期。
有没有办法在MySQL中完全执行此操作?
编辑: 在回答下面的评论时,2,3,4,5列需要相同,然后检查日期是否重叠(如果它们根本不重叠,可以让它们单独存在)。
存储过程会很棒,但是比使用游标循环遍历所有记录并将它们一对一地进行比较有更快的方法吗?
答案 0 :(得分:1)
执行此操作的一种方法是创建表的新副本,使用所需的新分组复制数据,然后重命名表以使用新表替换旧表。如果表格非常大,您最好使用SELECT ... INTO OUTFILE
将数据转储到磁盘,然后使用LOAD DATA INFILE
将其加载到新表中。
以下是我描述的第一种方法的示例:
CREATE TABLE your_table_new LIKE your_table;
INSERT INTO your_table_new(aff_id, aff_e1_id, aff_e1_type, aff_e2_id, aff_e2_type,
aff_start, aff_end)
SELECT NULL as aff_id, aff_e1_id, aff_e1_type, aff_e2_id, aff_e2_type,
MIN(aff_start), MAX(aff_end)
FROM your_table
GROUP BY aff_e1_id, aff_e1_type, aff_e2_id, aff_e2_type;
RENAME TABLE your_table TO your_table_old,
your_table_new TO your_table;
答案 1 :(得分:1)
您可以使用一系列删除/更新语句来解决它:
我认为您可以继续进行更新并在结束时执行一次删除操作,但根据数据量和重叠次数,这可能并不理想。
删除声明:
DELETE sub
FROM tab AS sub
INNER JOIN tab AS sup
ON sub.aff_e1_type = sup.aff_e1_type
AND sub.aff_e2_type = sup.aff_e2_type
AND sub.aff_e1_id = sup.aff_e1_id
AND sub.aff_e2_id = sup.aff_e2_id
AND ( ( sub.aff_start = sup.aff_start
AND sub.aff_end = sup.aff_end
AND sub.aff_id < sup.aff_id)
OR ( sub.aff_start > sup.aff_start
AND sub.aff_end <= sup.aff_end
AND sub.aff_id <> sup.aff_id)
OR ( sub.aff_start >= sup.aff_start
AND sub.aff_end < sup.aff_end
AND sub.aff_id <> sup.aff_id)
)
更新声明:
UPDATE tab AS row1
INNER JOIN tab AS row2
ON row1.aff_e1_type = row2.aff_e1_type
AND row1.aff_e2_type = row2.aff_e2_type
AND row1.aff_e1_id = row2.aff_e1_id
AND row1.aff_e2_id = row2.aff_e2_id
AND row1.aff_end >= row2.aff_start
AND row1.aff_start < row2.aff_start
AND row1.aff_id <> row2.aff_id
SET row1.aff_end = row2.aff_end