2012-04-20 34 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