Когда я выполняю следующий оператор запроса mySQLi в mySQL Workbench, он прекрасно работает со всеми строками, имеющими значения, отличные от NULL, - это происходит потому, что users.id - это столбец первичного ключа, который может не содержать нулей, а внешний объединение с артистами возвращает строки от пользователей, даже если в артистах нет связанной строки, но нет другого пути.

SELECT `users`.`id`,
       `users`.`username`,
       `users`.`id` AS 'users_id',
       `artists`.`id` AS 'artists_id',
       `artists`.*
  FROM `users` LEFT OUTER JOIN `artists`  ON `artists`.`users_id` = `users`.`id`
 WHERE IFNULL( `users`.`active`, -1 ) != 3
 ORDER BY `users`.`username`, `users`.`id`

Однако когда я выполняю один и тот же запрос в Sympfony v2.8 и Doctrine DBAL, используя следующую инструкцию, несколько элементов в конце массива возвращаемых строк имеют нулевые значения id, когда я смотрю на содержимое массива $ indexData в XDebugger :

$indexData = $conn->fetchAll( $sqlStmnt );

Обратите внимание, что ошибки не возвращаются, и оба запроса возвращают 51 строку.

0
user2505564 30 Ноя 2019 в 17:03
Исходя из того, что вы заявляете, ваша логика верна, users.id никогда не должен быть нулевым, поскольку он находится слева от внешнего соединения. Вы пробовали использовать сами значения, чтобы исключить возможность ошибки xdebug?
 – 
vhoang
30 Ноя 2019 в 22:24
Спасибо за ответ, к сожалению, я запрашиваю таблицу с неизвестными значениями, поэтому я действительно не могу использовать `` сами значения '', но я не верю, что это xdebugger, но поскольку выполнение запроса в моем коде вернуло null, поэтому затем я запустил код в отладчике. К счастью, я смог переписать запрос как два запроса, один для «входящих» и один для «не входящих» случаев, а затем объединить эти два случая вместе, что сработало.
 – 
user2505564
7 Дек 2019 в 00:55

1 ответ

Я переписал запрос SELECT на две части, чтобы удалить LEFT OUTER JOIN, а затем UNION'-две части и применил ту же сортировку, что и в исходном запросе, за исключением того, что мне пришлось использовать относительный порядок столбцов, потому что UNION не разрешить сортировку по столбцу исходной таблицы. Обратите внимание, что первая часть использует user.id, который отсутствует в подзапросе таблицы исполнителей, чтобы исключить строки, найденные во второй части.

(
  SELECT `users`.`id`,
         `users`.`username`,
         `users`.`id` AS 'users_id',
         `users`.*, NULL AS 'artists_id',
         NULL AS 'name',
         NULL AS 'artists_name_1st_char',
         NULL AS 'genre',
         NULL AS 'slug',
         NULL AS 'slug_count',
         NULL AS 'member_names',
         NULL AS 'background',
         NULL AS 'influences',
         NULL AS 'bio',
         NULL AS 'website',
         NULL AS 'instruments',
         NULL AS 'seeking',
         NULL AS 'youtube',
         NULL AS 'facebook',
         NULL AS 'instagram',
         NULL AS 'snapchat',
         NULL AS 'twitter'
    FROM `users`
   WHERE IFNULL( `users`.`active`, -1 ) != 3
     AND `users`.`id` not in ( SELECT `artists`.`users_id` FROM `artists`)
)
UNION ALL
(
  SELECT `users`.`id`,
         `users`.`username`,
         `users`.`id` AS 'users_id',
         `users`.*,
         `artists`.`id` AS 'artists_id',
         `artists`.`name` AS 'name',
         `artists`.`artists_name_1st_char` AS 'artists_name_1st_char',
         `artists`.`genre` AS 'genre',
         `artists`.`slug` AS 'slug',
         `artists`.`slug_count` AS 'slug_count',
         `artists`.`member_names` AS 'member_names',
         `artists`.`background` AS 'background',
         `artists`.`influences` AS 'influences',
         `artists`.`bio` AS 'bio',
         `artists`.`website` AS 'website',
         `artists`.`instruments` AS 'instruments',
         `artists`.`seeking` AS 'seeking',
         `artists`.`youtube` AS 'youtube',
         `artists`.`facebook` AS 'facebook',
         `artists`.`instagram` AS 'instagram',
         `artists`.`snapchat` AS 'snapchat',
         `artists`.`twitter` AS 'twitter'
    FROM `users` INNER JOIN `artists` ON `artists`.`users_id` = `users`.`id`
   WHERE IFNULL( `users`.`active`, -1 ) != 3
)
ORDER BY 2, 1

Этот запрос может фактически быть более эффективным, чем исходный запрос, потому что он не использует LEFT OUTER JOIN. Однако он не может использовать Artist. *, Чтобы запрос мог получить все столбцы в этой таблице. Вместо этого столбцы в художниках должны быть явно названы в предложении SELECT, поэтому изменения столбцов в таблице исполнителей должны учитываться в этом запросе. Для меня это только небольшое неудобство.

0
user2505564user2505564 30 Ноя 2019 в 22:04