ЛЕВЫЙ ВНЕШНИЙ ПРИСОЕДИНЯЙТЕСЬ К ДАННОМУ ОЖИДАННОМУ РЕЗУЛЬТАТУ - PullRequest
0 голосов
/ 16 сентября 2018

Я делаю простой запрос:

SELECT * FROM Bench LEFT JOIN  ASSIGNED_DOM 
        ON (Bench.B_id=ASSIGNED_DOM.B_id)  WHERE Bench.B_type=0 ;

Как и ожидалось, возвращаются все строки таблицы Bench, НО Если я пытаюсь получить обнаруженное поле B_id, которое было установлено в NULL. Затем я попытался с этим другим запросом, который должен быть полностью эквивалентен:

SELECT * FROM Bench LEFT JOIN  ASSIGNED_DOM USING (B_id)  WHERE Bench.B_type=0 ;

Но в этом случае поле B_id возвращается правильно. Что не так с первым запросом? Какая разница между ними?

Ответы [ 2 ]

0 голосов
/ 16 сентября 2018

Два запроса не эквивалентны.Согласно документации ,

Естественные объединения и объединения с использованием USING, включая варианты внешнего объединения, обрабатываются в соответствии со стандартом SQL: 2003.

Избыточные столбцы ЕСТЕСТВЕННОГО объединения не отображаются .

Это, в частности, сводится к следующему различию:

Предложение USING может быть переписано как предложение ON, которое сравнивает соответствующие столбцы.Однако, хотя USING и ON похожи, они не совсем одинаковы.

Что касается определения того, какие строки удовлетворяют условию соединения, оба соединения семантически идентичны.

Относительно определения того, какие столбцы отображать для расширения SELECT *, два объединения семантически не идентичны. Соединение USING выбирает объединенное значение соответствующих столбцов, , тогда как ONобъединение выбирает все столбцы из всех таблиц .

Итак, в вашем первом запросе есть два столбца с одинаковым именем bench.B_id, ASSIGNED_DOM.B_id, а во втором - один coalesce(bench.B_id, ASSIGNED_DOM.B_id) as B_id.

Это будет зависеть от вашего приложения /рамки, как именно первый случай будет обработан.Например, клиент MySQL или phpmyadmin просто отобразит все столбцы.Некоторые фреймворки могут каким-то образом изменять имена, чтобы сделать их уникальными. В частности,

php (и я предполагаю, что вы используете это) не будет: если вы используете $row['B_id'], он вернет последнееoccurance (хотя это поведение не указано), поэтому в вашем случае вы получите ASSIGNED_DOM.B_id.Однако вы по-прежнему можете обращаться к обоим столбцам с помощью их индекса (например, $row[0], $row[1]), но только к одному из них с одинаковым именем столбца.

Чтобы предотвратить такие проблемы, вы можете / должны использовать псевдонимы, например, select bench.B_id as bench_B_id, ASSIGNED_DOM.B_id as ASSIGNED_DOM_B_id, ....

0 голосов
/ 16 сентября 2018

Значения во второй таблице перезаписывают значения в первой, если имя столбца совпадает. Попробуйте использовать псевдоним в вашем запросе

SELECT Bench.B_id AS bid1, ASSIGNED_DOM.B_id AS bid2 
FROM Bench 
LEFT JOIN  ASSIGNED_DOM ON (Bench.B_id=ASSIGNED_DOM.B_id) 
WHERE Bench.B_type=0;
...