1

问题陈述如下:

-一个有一个带有结构的表INIT

(number1 INT not null, number2 INT not null, ..., number7 INT not null)

- 我想将表 INIT 的所有行插入到表“选项卡”中,但我不想在“选项卡”中有 2 行,这样一个是另一个的排列。因此,例如,如果 (1,2,3,7,19,21,6) 和 (19,2,3,7,1,21,6) 是 INIT 中的行,那么其中只有一个具有最终出现在“标签”中。它们中的哪一个最终出现在“选项卡”中并不重要。

- 我下面的代码的作用如下:我保留了一个与 INIT 结构相同的辅助表“aux”。我遍历表 INIT 的所有行,对于 INIT 中的每一行,我按其组件的递增顺序对其进行排序,因此如果 (1,2,3,7,19,21,6) 是 INIT 中的一行,我对其进行排序(1,2,3,6,7,19,21) 并检查它是否在“辅助”中。如果是我继续下一行。否则,我在“选项卡”中插入 (1,2,3,7,19,21,6)。

我在包含 300,000 行的表 INIT 上运行了这个过程,我估计它需要超过 7 个小时才能运行。我想知道如何提高此程序的运行时间。

DECLARE done BOOLEAN default 0;
DECLARE n1,n2,n3,n4,n5,n6,n7 INT;
DECLARE o1,o2,o3,o4,o5,o6,o7 INT;
DECLARE my_cursor cursor  FOR select * from INIT;
DECLARE CONTINUE HANDLER FOR SQLSTATE '02000' SET done=1;       
OPEN my_cursor;

drop table if exists aux;
create table aux(
  number1 INT not null,
  number2 INT not null,
  number3 INT not null,
  number4 INT not null,
  number5 INT not null,
  number6 INT not null,
  number7 INT not null,
 );
 create table temp( number INT );

REPEAT
   truncate table temp;

   FETCH my_cursor INTO n1,n2,n3,n4,n5,n6,n7;
        INSERT INTO temp values(n1);
        INSERT INTO temp values(n2);    
        INSERT INTO temp values(n3);
        INSERT INTO temp values(n4);
        INSERT INTO temp values(n5);
        INSERT INTO temp values(n6);
        INSERT INTO temp values(n7);
        BEGIN
           DECLARE done2 BOOLEAN default 0;
           DECLARE my_cursor2 cursor  FOR select * from temp order by number;  
           OPEN my_cursor2;
             FETCH my_cursor2 INTO o1;
             FETCH my_cursor2 INTO o2;
             FETCH my_cursor2 INTO o3;
             FETCH my_cursor2 INTO o4;
             FETCH my_cursor2 INTO o5;
             FETCH my_cursor2 INTO o6;
             FETCH my_cursor2 INTO o7;

             IF NOT EXISTS (SELECT * FROM aux where number1=o1 AND number2=o2 AND number3=o3 
                            AND number4=o4 AND number5 = o5 AND number6 = o6 AND number7=o7 ) 
             THEN
                 INSERT INTO tab VALUES (n1,n2,n3,n4,n5,n6,n7);
             END IF;
           CLOSE my_cursor2;
         END;
UNTIL done END REPEAT;
CLOSE my_cursor;

编辑: - 在 INIT 的每一行中,所有整数都是不同的。-INIT的主键是(number1,number2,...,number7)

4

2 回答 2

1

您正在对每一行进行大量查询……这不是一个好方法。

相反,您可以使用一些数据库功夫在没有存储过程的情况下完成工作:

insert into tab
select number1, number2, number3, number4, number5, number6, number7 from (
  select number1, number2, number3, number4, number5, number6, number7, 
    group_concat(number order by number) as sig from (
      select number1, number2, number3, number4, number5, number6, number7, number1 as number
      union all select number1, number2, number3, number4, number5, number6, number7, number2
      union all select number1, number2, number3, number4, number5, number6, number7, number3
      union all select number1, number2, number3, number4, number5, number6, number7, number4
      union all select number1, number2, number3, number4, number5, number6, number7, number5
      union all select number1, number2, number3, number4, number5, number6, number7, number6
      union all select number1, number2, number3, number4, number5, number6, number7, number7) a
) group by sig) b

这里涉及的关键技巧是:

  • 内部选择允许group_concat按照标准顺序对数字进行分组,以便可以比较组合
  • group_concatwith order by 为您提供数字的唯一签名
  • 在 mysql 中使用group by 聚合为您提供每个分组列值的第一行

顺便说一句,正确的术语是组合而不是排列

另外,我还没有测试过这个,所以可能有一个错位的支架等,但它应该“基本上”工作

于 2012-04-20T01:15:26.133 回答
0

mysqlism,比较使用GROUP_CONCAT:

create table p -- data source
(
  grp int auto_increment primary key, n1 int, n2 int, n3 int, n4 int, n5 int, n6 int, n7 int  
  );


insert into p(n1,n2,n3,n4,n5,n6,n7) 
select 1,2,3,7,19,21,6 union
select 19,2,3,7,1,21,6 union
select 20,2,3,7,1,21,6;


create table g -- staging table
(
  grp int,
  n int
);

insert into g(grp, n)
select grp, n
from
(
    select grp, n1 as n from p
    union all
    select grp, n2 from p
    union all
    select grp, n3 from p
    union all
    select grp, n4 from p
    union all
    select grp, n5 from p
    union all
    select grp, n6 from p
    union all
    select grp, n7 from p
) as x

独特的提取器:

select grp, n1, n2, n3, n4, n5, n6, n7
from p
where grp in
(
 select min(grp) as first_elem -- select only one among duplicates
 from
 ( 
    select grp, group_concat(n order by n) as comb
    from g
    group by grp
 ) as x
 group by comb
);

基本上,对数字进行排序,这样它们更适合组合比较,然后使用一些 MySqlism 来简化比较逻辑,即使用 group_concat

现场测试:http ://sqlfiddle.com/#!2/7b61f/1

于 2012-04-20T02:08:43.680 回答