2016-08-04 50 views

回答

2

如果有大量值,請將它們加載到臨時表中,並將其加入到該表中。

$sql = "select t.* from temptable t left join foo f on f.id = t.id where f.id is null"; 
+0

如果您正在執行'VARCHAR'值,則需要**才能轉義,因此不能只是連接。 – tadman

+1

@BillKarwin ooops!感謝您的領導,更正了querey – Ray

+0

@BillKarwin所有更新都反映了OP期望的結果! – Ray

0

您可以使用array_diff()select distinct ...組合,以獲得理想的效果迅速:

$array = [1,2,3,4,5,6,7,8,9,0]; 
$mysql_array = []; 
// $mysql_array = [3,7,9]; // uncomment this if you wish to test without DB data 

$sql = 'select distinct id as id from mysql_table'; 

// mysql querying functions or PDO or whatever 

while(looping results) 
{ 
    $mysql_array[] = $row['id']; 
} 

print_r(array_diff($array, $mysql_array)); 

// If using $mysql_array = [3,7,9]; test data then you will get this result 
/* 
Array 
(
    [0] => 1 
    [1] => 2 
    [3] => 4 
    [4] => 5 
    [5] => 6 
    [7] => 8 
    [9] => 0 
) 
*/ 

重要提示:

上面介紹的方法具有的潛力如果distinct查詢r耗盡了可用於PHP腳本的可用內存能夠處理一百萬條或更多的記錄。

+0

這是一個壞主意,因爲它會消耗PHP腳本中無限量的內存,具體取決於MySQL表中不同ID的數量。這可能是數十億美元。 –

+0

@BillKarwin是真的,但OP沒有指定他們的表的大小。我選擇在這裏留下這個答案,因爲總是有不止一種做事方式。我會記下你指出的內存問題。謝謝! – MonkeyZeus

2

對這個線程的幾個答案和評論誤解了OP所要求的。 OP沒有要求MySQL表中的值不在PHP數組中。 OP詢問了相反的情況:PHP數組中的值不在MySQL表中。

將這些值加載到臨時表中。我假設一個包含整數的變量$array。這是一次插入多行的代碼。如果這會生成一個比max_allowed_packet更長的INSERT語句,則分批加載該數組。

$pdo->query("CREATE TEMPORARY TABLE values_to_search (value INT PRIMARY KEY)"); 

$sql = "INSERT INTO values_to_search (value) VALUES " 
    . implode(",", array_fill(1, count($array), "(?)")); 
$stmt = $pdo->prepare($sql); 
$stmt->execute($array); 

對正在搜索的表執行外連接。沒有匹配的地方,價值不存在。

$sql = "SELECT v.value 
    FROM values_to_search AS v 
    LEFT OUTER JOIN mytable t ON v.value = t.value 
    WHERE t.value IS NULL"; 
$stmt = $pdo->query($sql); 
$results = $stmt->fetchAll(PDO::FETCH_NUM); 
+0

嗨,謝謝你的回答。我使用這個解決方案,它可以工作,但只需要140秒就可以完成17000行的外連接。這是正常的嗎? –

+0

您應該在要加入的值列上有一個索引,但即使沒有索引,我也認爲140秒太長。您的服務器上可能有問題。例如,它是交換?讓系統管理員檢查出來。 –

+0

我使用3核心和4Gb內存的VPS,它比較17k線57k現在需要160秒。 –

0

我建議的替代解決方案,基於該OP的上下文暗示所有已經註冊的值是要探索這一事實。
編輯:看@MonkeyZeus答案我意識到他們可能已經註冊了不止一次,所以我在下面的查詢中添加了DISTINCT

可能會更快,因爲它只使用一個簡單的查詢......但不確定,因爲它也迭代了一個巨大的數組。
另一方面,它不會導致內存問題,因爲只使用fetch(),而不是fetchAll()

假設value是所涉及的列的名稱和$searched_values是含有所搜索的值(簡單)陣列:

// make known values and searched values sorted the same 
$stmt = $pdo->query('SELECT DISTINCT value FROM mytable ORDER BY value'); 
sort($searched_values); 

$unknown_values = []; 
$known_value = NULL; 

foreach ($searched_values as $searched_value) { 
    if (!$known_value) { 
     // previous known_value already consumed (or end), try to get next one 
     $known_value = $stmt->fetch()['value']; 
    } 
    if ($known_value == $searched_value) { 
     // consume current known_value 
     $known_value = NULL; 
    } else { 
     // otherwise current $searched_value is unknown, register it: 
     $unknown[] = $searched_value; 
    } 
} 
相關問題