2011-05-11 24 views
4

我有可能會存儲整數數十萬的表:從一組值中,我如何找到未存儲在表格列中的值?

desc id_key_table; 

+----------------+--------------+------+-----+---------+-------+ 
| Field   | Type   | Null | Key | Default | Extra | 
+----------------+--------------+------+-----+---------+-------+ 
| id_key   | int(16)  | NO | PRI | NULL |  | 
+----------------+--------------+------+-----+---------+-------+ 

從一個計劃,我有一個大的整數集。我想看看哪些整數不在上面的id_key列中。

到目前爲止,我想出了以下方法:

1)遍歷每個整數,執行:

select count(*) count from id_key_table where id_key = :id_key 

當計數爲0的id_key從表中缺少。

這似乎是一個可怕的,可怕的方式來做到這一點。


2)創建一個臨時表,將每個值插入到臨時表中,然後對這兩個表執行JOIN。

create temporary table id_key_table_temp (id_key int(16) primary key); 

insert into id_key_table_temp values (1),(2),(3),...,(500),(501); 

select temp.id_key 
from id_key_table_temp temp left join id_key_table as main 
     on temp.id_key = main.id_key 
where main.killID is null; 

drop table id_key_table_temp; 

這似乎是最好的方法,但是,我敢肯定還有更好的方法,我還沒有想到。我寧願不必創建臨時表並使用一個查詢來確定哪些整數缺失。

是否有適合此類搜索的查詢?

(MySQL的)

+0

第二種選擇是最好的。 (檢查速度的3種可能的寫法查詢方式,你編寫的'LEFT JOIN - IS NULL','NOT IN'版本和'NOT EXISTS'方式。通常MySQL中的第一或第三更快。 – 2011-05-11 16:56:44

+0

我想你想檢查的id_keys不是順序的,(1-501)只是一個例子。 – 2011-05-11 16:58:13

+0

ypercube,正確,密鑰不是順序的。實際上可能有非常大的差距:例如100000 - 150000填充缺失的隨機數,然後230000 - 400000填充缺失的隨機數等。 – Clinton 2011-05-11 17:39:05

回答

4

在問題中給出的第二個例子中使用你的代碼,我創建了兩個存儲過程(SP):1個SP加載素數作爲密鑰的樣品臺,其他SP找到缺少的整數。

這是第一個SP:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `test`.`CreateSampleTable` $$ 
CREATE PROCEDURE `test`.`CreateSampleTable` (maxinttoload INT) 
BEGIN 

    DECLARE X,OKTOUSE,MAXLOOP INT; 

    DROP TABLE IF EXISTS test.id_key_table; 
    CREATE TABLE test.id_key_table (id_key INT(16)) ENGINE=MyISAM; 

    SET X=2; 
    WHILE X <= maxinttoload DO 
    INSERT INTO test.id_key_table VALUES (X); 
    SET X = X + 1; 
    END WHILE; 
    ALTER TABLE test.id_key_table ADD PRIMARY KEY (id_key); 

    SET MAXLOOP = FLOOR(SQRT(maxinttoload)); 
    SET X = 2; 
    WHILE X <= MAXLOOP DO 
    DELETE FROM test.id_key_table WHERE MOD(id_key,X) = 0 AND id_key > X; 
    SELECT MIN(id_key) INTO OKTOUSE FROM test.id_key_table WHERE id_key > X; 
    SET X = OKTOUSE; 
    END WHILE; 
    OPTIMIZE TABLE test.id_key_table; 

    SELECT * FROM test.id_key_table; 

END $$ 

DELIMITER ; 

這裏是第二個SP:

DELIMITER $$ 

DROP PROCEDURE IF EXISTS `test`.`GetMissingIntegers` $$ 
CREATE PROCEDURE `test`.`GetMissingIntegers` (maxinttoload INT) 
BEGIN 

    DECLARE X INT; 

    DROP TABLE IF EXISTS test.id_key_table_temp; 
    CREATE TEMPORARY TABLE test.id_key_table_temp (id_key INT(16)) ENGINE=MyISAM; 

    SET X=1; 
    WHILE X <= maxinttoload DO 
    INSERT INTO test.id_key_table_temp VALUES (X); 
    SET X = X + 1; 
    END WHILE; 
    ALTER TABLE test.id_key_table_temp ADD PRIMARY KEY (id_key); 

    SELECT temp.id_key FROM test.id_key_table_temp temp 
    LEFT JOIN test.id_key_table main USING (id_key) 
    WHERE main.id_key IS NULL; 

END $$ 

DELIMITER ; 

下面是使用25號創建素數第一SP的樣品試驗:

mysql> CALL test.CreateSampleTable(25); 
+-------------------+----------+----------+----------+ 
| Table    | Op  | Msg_type | Msg_text | 
+-------------------+----------+----------+----------+ 
| test.id_key_table | optimize | status | OK  | 
+-------------------+----------+----------+----------+ 
1 row in set (0.16 sec) 

+--------+ 
| id_key | 
+--------+ 
|  2 | 
|  3 | 
|  5 | 
|  7 | 
|  11 | 
|  13 | 
|  17 | 
|  19 | 
|  23 | 
+--------+ 
9 rows in set (0.17 sec) 

mysql> 

下面是使用25作爲完整列表比較的第二個SP的運行:

mysql> CALL test.GetMissingIntegers(25); 
+--------+ 
| id_key | 
+--------+ 
|  1 | 
|  4 | 
|  6 | 
|  8 | 
|  9 | 
|  10 | 
|  12 | 
|  14 | 
|  15 | 
|  16 | 
|  18 | 
|  20 | 
|  21 | 
|  22 | 
|  24 | 
|  25 | 
+--------+ 
16 rows in set (0.03 sec) 

Query OK, 0 rows affected (0.05 sec) 

mysql> 

雖然這個解決方案對於小樣本來說是可以的,但是大列表卻成爲一個令人頭痛的問題。您可能想要保留臨時表(不要一次又一次使用CREATE TEMPORARY TABLE,只使用CREATE TABLE一次),永久加載數字1 .. MAX(id_key)並通過id_key_table上的觸發器填充該永久臨時表。

只是一個問題,因爲我很好奇:你是否這樣做,看看是否可以重用表中的auto_increment鍵?

+0

「您是否正在執行此操作以查看錶中的auto_increment鍵是否可以重用???」不,那是瘋狂的談話。我收到的數據集足以提供唯一的標識符,並且只是試圖不重新處理已處理的數據。數據將傾向於從不同的來源重複出現(但仍提供相同的一致唯一標識符)。 – Clinton 2011-05-11 17:24:37

+0

@Clinton我見過其他開發者實際上在做這個瘋狂的演講,所以我聽到你的聲音。 – RolandoMySQLDBA 2011-05-11 17:28:14

+0

現在誰在點! +1好回答 – DTest 2011-05-11 18:27:16

相關問題