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

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 возвращается правильно. Что не так с первым запросом? Какая разница между ними?

0
Giuseppe Levi 16 Сен 2018 в 20:14

2 ответа

Лучший ответ

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

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

Избыточные столбцы NATURAL соединения не отображаются .

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

Предложение 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'], он вернет последнее событие (хотя это поведение не указано), поэтому в вашем случае вы будете получить 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, ... .

1
Solarflare 16 Сен 2018 в 20:53

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

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;
1
Bart 16 Сен 2018 в 18:25