Скажем, у меня есть массив строк в массиве php с именем $ foo с несколькими сотнями записей, и у меня есть таблица MySQL «people», в которой есть поле с именем «name» с несколькими тысячами записей. Каков эффективный способ узнать, какие строки в $ foo не являются «именем» в записи в «people», не отправляя запрос для каждой строки в $ foo?
Итак, я хочу узнать, какие строки в $ foo еще не были введены в 'people'.
Обратите внимание, что очевидно, что все данные должны быть в одном поле в одной точке. Цель состоит в том, чтобы сделать это одновременно с минимизацией количества запросов и объема обработки php.






Я бы поместил ваши данные $ foo в другую таблицу и сделал ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ с вашей таблицей имен. В противном случае существует не так много отличных способов сделать это, которые в какой-то момент не включали бы итерацию.
Я не уверен, что есть более эффективный способ сделать это, кроме отправки всех строк в базу данных.
В основном есть два варианта: получить список всех строк в MySQL и вытащить их в PHP и провести сравнения или отправить список всех строк на сервер MySQL и позволить ему сделать сравнения. MySQL будет выполнять сравнения намного быстрее, чем PHP, если только список в базе данных не будет намного меньше, чем список в PHP.
Вы можете создать временную таблицу, но в любом случае вы отправите все данные в базу данных.
Вы можете привести пример того, как может выглядеть длинный оператор выбора?
Если подумать, длинный выбор, вероятно, не сработает, вам понадобится идея временной таблицы, принятая в качестве правильного ответа.
Для нескольких сотен записей просто используйте array_diff () или array_diff_assoc ()
Лучшее, что я могу придумать без использования временной таблицы:
$list = join(",", $foo);
// fetch all rows of the result of
// "SELECT name FROM people WHERE name IN($list)"
// into an array $result
$missing_names = array_diff($foo, $result);
Обратите внимание, что если $ foo содержит пользовательский ввод, его сначала нужно экранировать.
Ага! Заполнителей нет! Не цитируется! Никаких побегов!
Ну, закомментированные строки, очевидно, являются псевдокодом. И я упомянул об отсутствии побегов, не так ли? Однако отсутствие цитирования было упущением, мое плохое.
$query = 'SELECT name FROM table WHERE name != '.implode(' OR name != '. $foo);
Да уж, похоже, что он вообще не будет хорошо масштабироваться.
Это должно быть «И», а не «ИЛИ».
CREATE TEMPORARY TABLE PhpArray (name varchar(50));
-- you can probably do this more efficiently
INSERT INTO PhpArray VALUES ($foo[0]), ($foo[1]), ...;
SELECT People.*
FROM People
LEFT OUTER JOIN PhpArray USING (name)
WHERE PhpArray.name IS NULL;
А как насчет следующего:
SELECT name FROM people WHERE name IN (imploded list of names)array_diff()Если вы хотите сделать это полностью на SQL:
INSERT ... SELECT из второй временной таблицы в таблицу людей.Ни один из них не будет очень быстрым, хотя второй вариант может быть немного быстрее.
как бы вы использовали LEFT JOIN, чтобы вернуть дату $ foo нет в таблице имен?