Здесь я уменьшил ваш код, или, по крайней мере, код, который на самом деле делает вещи
$result1 = $this->pdo->query('
SELECT
B.idB,
B.name
FROM
B
LEFT JOIN
A ON A.idB=B.idB
WHERE
B.status=2 AND IS NULL A.ibB
')->fetchAll(PDO::FETCH_ASSOC);
$stmt = $this->pdo->prepare('
INSERT INTO
A(idB,name) VALUES (:idB,:name)'
);
foreach ($result1 as $row) $stmt->execute($row);
Предполагая, что у вас было правильно, давайте посмотрим на JOIN
select * from B where status=2
select * from A where idB='".$row['idB']."'
//and the results of A are $row
$row['name'] //<-- dont forget this field
Если A.idB
= B.idB
, мы можем присоединиться к этому. Тогда вы используете только idB
и name
, поэтому вместо *
мы можем использовать эти 2 как из B (потому что $row
был из B
).
Мы можем отобразить это как половину путевой точки:
select B.idB,B.name from B where status=2
select * from A where A.idB=B.idB
Который, когда мы присоединяемся к ним:
select
B.idB,B.name
from
B
LEFT JOIN #left JOIN
A ON A.idB=B.idB
WHERE
B.status=2
AND
IS NULL A.ibB #records from B where no A.idB exists.
AS Указано в комментариях:
В основном вам нужны все записи из B, у которых нет записи, совпадающей с A.
Для этого мы можем использовать левое соединение. Который будет возвращать все записи со стороны LEFT в JOIN (таблица B
) независимо от того, есть ли у них запись JOINED в A
с правой стороны.
Тогда нам просто нужно сохранить записи с левой стороны B
, которые имеют null
для значения A.ibB
, что мы можем сделать с IS NULL A.ibB
.
Эти пропущенные записи - те, которые мы хотим вставить в конце:
Тогда давайте посмотрим на код PDO:
$q1=$this->pdo->query($sql1);
/// $q1->execute(); <--------------------- no need for this
$result1=$q1->fetchAll(PDO::FETCH_ASSOC);
Теперь $this->pdo->query()
возвращает false или объект PDOStatement, а [PDOSTatement]->fetchAll()
может быть присоединен с помощью return.
Так что мы можем покончить со всеми этими локальными переменными и записать это так.
$result1 = $this->pdo->query($sql1)->fetchAll(PDO::FETCH_ASSOC);
Это лучше всего работает, если у вас есть PDO, настроенный на выдачу исключений, тогда вам не нужно беспокоиться о том, что он возвращает FALSE в случае сбоя, поскольку вместо этого он просто генерирует исключение.
Так же, как мы используем строку SQL только один раз, мы можем просто исправить это и избавиться от $sql1
. То же самое верно для запроса вставки:
$stmt = $this->pdo->prepare('INSERT INTO A(idB,name) VALUES (:idB,:name)');
foreach ($result1 as $row) $stmt->execute($row);
Но с одним или двумя примечаниями. ЗДЕСЬ, потому что мы вернули то, что мы извлекли из первого запроса, только к тому, что нам нужно, и все названо одинаково, мы можем просто поместить $row
прямо в execute
. Другая вещь, на которую стоит обратить внимание, это подготовить запрос вне цикла. Мы можем повторно использовать PDOStatement
столько раз, сколько захотим, и БД нужно только интерпретировать SQL в первый раз, что экономит нам немного производительности.
Summery
Если вам легче читать, сохраняйте локальные переменные. Мне нравится от них избавляться, потому что я не очень люблю печатать, потому что я пишу тонну кода, поэтому я стараюсь писать столько, сколько мне нужно, для выполнения работы. Но я давно этим занимаюсь, поэтому довольно легко могу читать более сложный код.
Я просто хотел показать это таким образом, потому что, я не думаю, что это хорошо отражено во многих примерах того, насколько вы можете уменьшить свой код и при этом сделать то же самое. И чем меньше кода, тем меньше кода для отладки (до предела).
Приветствие.