由于日期重叠,从MySQL表中删除冗余条目

时间:2011-05-17 20:44:33

标签: mysql sql date

我有一个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列需要相同,然后检查日期是否重叠(如果它们根本不重叠,可以让它们单独存在)。

存储过程会很棒,但是比使用游标循环遍历所有记录并将它们一对一地进行比较有更快的方法吗?

2 个答案:

答案 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)

您可以使用一系列删除/更新语句来解决它:

  • 删除完全在另一个范围内的所有范围
  • 更新任何结束日期> =另一个范围的开始日期
  • 的范围
  • 重复(假设您可能有一系列对同一个ID重叠的行),直到您的更新语句不更新任何行

我认为您可以继续进行更新并在结束时执行一次删除操作,但根据数据量和重叠次数,这可能并不理想。

删除声明:

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