2012-04-20 37 views
1

问题的声明如下:这个SQL代码如何消除排列得到改善?

-One与结构的表INIT

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

-I要插入到表“标签”表INIT的所有行,但我不知道想要 在'tab'中有两行,这样一个是另一个的排列。因此,举例来说,如果(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中的一行,I对它进行排序(1,2,3,6,7,19,21)并检查它是否在'aux'中。如果是 我继续下一行。否则,我在'tab'中插入(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)

+0

不知道波西米亚的解决方案将如何工作(也不怀疑它),但问题......每一行都可以重复任何数字吗? – DRapp 2012-04-20 01:25:20

+0

你的INIT表是否有主键? – 2012-04-20 01:33:53

+0

我编辑了我的消息。是的,INIT表有一个主键(所有列),并且每个单一行都不能重复。 – user1261701 2012-04-20 01:43:31

回答

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_concat与订单通过给你一个独特的标志ATURE使用group by数字
  • 没有在MySQL聚集为您提供第一行对各组按列值

BTW,正确的说法是组合排列

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

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

+0

不会工作,因为'工会'删除重复:( – Bohemian 2012-04-20 04:11:27

+0

不要郁闷,保留重复只是将'UNION'更改为'联盟所有';-) – 2012-04-20 04:39:11