Подскажите как будет правильно, чтобы минимизировать количество запросов к базе?

Sergey_555

Новичок
Поиск должен происходить в одном поле базы нескольких значений.

Есть форма, в ней указываются значения которые необходимо найти в одном из полей.

Допустим таблица базы имеет следующий вид



В форме для поиска указали 5 значений (“a”,”b”,”e”,”g”,”u”).

Теперь нужно произвести поиск всех 5-ти значений в таблице (найдет три совпадения) и вывести на обозрение те, которые не нашлись в таблице (”e” и ”u”).

Собственно вопрос как лучше?

1. Создать массив (arr_1) со значениями которые нужно найти (“a”,”b”,”e”,”g”,”u”) и из таблицы получить массив (arr_2) в который занести все значения поля 2.
Затем из массива (arr_1) выкинуть все значения которые совпали и вывести то, что осталось.

2. Вести в базе в поле 2 поиск сразу всех 5-ти значений

SELECT * FROM таблица WHERE поле2 IN (“a”,”b”,”e”,”g”,”u”);

А как тогда выкинуть те которые совпали и оставить только те которые не нашлись (уникальные) ?
 

Sergey_555

Новичок
Если я правильно понимаю, то IN нужен для того, чтобы выбрать все записи в которых есть одно из значений в IN, а NOT IN наоборот выберет из таблицы все записи в которых не встречаются заданные в нем значения.
То есть IN выберет строки ( 1, 5, 10 ), а NOT IN ( 2, 3, 4, 6, 7, 8, 9 )

Но мне нужно, чтобы остались те из указанных в форме отправки значения, которые не нашлись в базе (”e” и ”u”),
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Sergey_555, если ты напишешь условие, WHERE field NOT IN ('a', 'b', 'c', 'e', 'u') и поле field не принимает значения 'e' или 'u', то записи с таким значением будут выбраны.
 

Sergey_555

Новичок
Я наверное не правильно задал вопрос изначально.
Я понял, что будут выбраны все строки где поле field не принимает значения 'e' или 'u', но дело в том, что в базе на момент запроса не существует строк в которых поле field имеет значения 'e' или 'u'

Теперь в базе ищем совпадения, после чего выводим сообщение типа " из выбранных вами, свободны только 'e' и 'u' "
Мне не нужно выводить то, что нашлось или не нашлось в базе ( там нужно лишь сверить )

Вот и интересует как минимизировать запросы к базе.
1 Загнать в один массив то, что выберет пользователь, а в другой массив загнать значения поля field абсолютно всех строк. Дальше уже к базе не обращаемся, а проделываем нужные манипуляции с массивами.
Либо другой вариант
2 Сразу в поле field вести поиск 5-ти значений, перебирая все строки.

В каком случае будет меньше запросов к базе ?
 

stalxed

Новичок
1) У Вас есть массив проверяемых значений
PHP:
$allValues = ['a', 'b', 'e', 'g', 'u'];
2) Получаете список уникальных занятых значений
SELECT DISTINCT(`поле2`) AS поле2 FROM `таблица` WHERE поле2 IN (“a”,”b”,”e”,”g”,”u”);
допустим вы его получили в переменную $usedValues;
3) Вычислите не использованные
PHP:
$result = array_diff($allValues, $usedValues);
 

AnrDaemon

Продвинутый новичок
stalxed, тебя не учили, что всё, что SQL сервер может сделать сам, он должен делать сам? В твоём примере ты делаешь дурную работу, когда мог сразу получить от SQL сервера нужный ответ.
 

stalxed

Новичок
stalxed, тебя не учили, что всё, что SQL сервер может сделать сам, он должен делать сам? В твоём примере ты делаешь дурную работу, когда мог сразу получить от SQL сервера нужный ответ.
Во время чтения книги по регулярным выражениям Джефри Фридла мне глубоко врезались его слова, что некоторые операции лучше сделать клиентским кодом, а не городить сложные регулярные выражения(имелось в виду, что легкая регулярка + дообработка результата клиентским кодом лучше, чем сложная регулярка).
Я считаю, что данное правило относится и к SQL.
Если операция легко делается в ЯП, зачем это переносить в базу данных.
Тем более в примере выше модель выглядит очень чисто:
PHP:
<?php
class SomeManager
{
  // come code

    public function findFree(array $values)
    {
        return array_diff($values, $this->findUsed($values));
    }

    public function findUsed(array $values)
    {
        return $this->repository->findUsed($values); // обращение к бд
    }
}
 
Последнее редактирование:

WMix

герр M:)ller
Партнер клуба
AnrDaemon, чет не соображу, как ты предлагаешь.
надеюсь не (select 'a' union select 'b' ...) as t left join letters...
 
Последнее редактирование:

cia

Новичок
stalxed, тебя не учили, что всё, что SQL сервер может сделать сам, он должен делать сам? В твоём примере ты делаешь дурную работу, когда мог сразу получить от SQL сервера нужный ответ.
Мне кажется что это не совсем верный подход. SQL должен делать то, что в конкретной ситуации он может сделать более эффективно, нежели PHP или другой клиент sql. Кроме того никогда не стоит забывать о распределении нагрузки. В большинстве случаев сервер sql (если это отдельный физический сервер) нагружен сильнее нежели сервер приложения. Поэтому имеет смысл облегчать работу sql-сервера и нагружать клиента. С другой стороны есть ещё канал связи между двумя серверами, даже если они общаются через сокет. И в отдельных случаях имеет смысл постараться снизить этот трафик, перекладывая часть логики на субд.
Но в большинстве случаев надо просто доверять субд делать то, что он умеет делать эффективно.
В конкретной ситуации я, например, не вижу другого варианта кроме предложенного stalxed.
 
  • Like
Реакции: WMix

AnrDaemon

Продвинутый новичок
AnrDaemon, чет не соображу, как ты предлагаешь.
надеюсь не (select 'a' union select 'b' ...) as t left join letters...
Э… вообще-то простые решение - самые правильные. Не?
Код:
SELECT `v` FROM `test1` WHERE `v` IN (3, 4, 5, 6, 7, 8) AND `v` NOT IN (4, 6);

Array
(
    [0] => Array
        (
            [v] => 4
        )

    [1] => Array
        (
            [v] => 6
        )

    [2] => Array
        (
            [v] => 7
        )

    [3] => Array
        (
            [v] => 8
        )

)
 

cia

Новичок
В результат не попадёт, например, "3", если в test1 нет "3".
 

AnrDaemon

Продвинутый новичок
Вопрос, как у тебя в выборе оказалась "3", если её нет в БД?…
 

cia

Новичок
Вопрос, как у тебя в выборе оказалась "3", если её нет в БД?…
Это не у меня. Это у топикстартера. Внимательнее прочти что он писал в первом и третьем посте.
 

AnrDaemon

Продвинутый новичок
Может, тогда в консерватории что-то поправить? Если у ТС условие берётся из одного места, решение из другого, а результат проверяется по третьему - откуда он вообще знает, что результат соответствует условию задачи?
 

c0dex

web.dev 2002-...
Команда форума
Партнер клуба
Может просто читать внимательно?) Я тоже не с первого раза понял что ему надо.
 
  • Like
Реакции: WMix

WMix

герр M:)ller
Партнер клуба
AnrDaemon, как это
Код:
`v` IN (...4, ... 6...) AND `v` NOT IN (4, 6);
не кажется тебе самому что гонишь?
 

AnrDaemon

Продвинутый новичок
WMix, я проверил… Работает. :p

Может просто читать внимательно?) Я тоже не с первого раза понял что ему надо.
Я внимательно читал. Но я не люблю задач, условие которых сформулировано из рук вон плохо и само с собой не стыкуется. Поддерживать потом такой код - то ещё "удовольствие".
 

WMix

герр M:)ller
Партнер клуба
нук задампи, для меня это революция
 
Сверху