PHP & MYSQL: как разрешать неоднозначные имена столбцов в операции JOIN?

У меня есть две таблицы в моей базе данных:

NEWS ('id' – идентификатор новостей, «пользователь» – идентификатор пользователя автора)

USERS ('id' – идентификатор пользователя)

Я хочу сделать SELECT * FROM news JOIN users ON news.user = user.id , теперь, когда я получаю результаты в PHP, это что-то вроде:

$row = mysql_fetch_array($result) и получить имена столбцов по $row['column-name'] … как получить идентификатор новостей и идентификатор пользователя с одинаковым именем столбца?

ОБНОВЛЕНИЕ: Спасибо всем за быстрые ответы. Алиасы кажутся лучшим решением.

Вы можете установить псевдонимы для столбцов, которые вы выбираете:

 $query = 'SELECT news.id AS newsId, user.id AS userId, [OTHER FIELDS HERE] FROM news JOIN users ON news.user = user.id' 

Вы можете либо использовать числовые индексы ( $row[0] ), либо лучше использовать AS в MySQL:

SELECT *, user.id AS user_id FROM ...

Я просто понял это. Вероятно, это плохая практика, но в этом случае я работал для меня.

Я один из ленивых людей, которые не хотят псевдонима или записывают каждое имя столбца с префиксом таблицы.

Вы можете выбрать все столбцы из конкретной таблицы, используя table_name.* В своем заявлении select.

Когда вы дублируете имена столбцов, mysql будет переписываться с первого на последний. Данные из первого дублированного имени столбца будут перезаписаны, когда он снова встретит это имя столбца. Таким образом, дублируется имя столбца, которое приходит в последних победах.

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

Пример:

 SELECT table1.* , table2.* , table3.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup; 

В приведенном выше примере значение dup я получаю, будет из table3 .

Что делать, если я хочу, чтобы dup был значением из table1 ?

Тогда мне нужно это сделать:

 SELECT table3.* , table2.* , table1.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup; 

Теперь table1 приходит последним, поэтому значение dup будет значением из таблицы1.

Я получил значение, которое я хотел для dup не выписывая каждый лишний столбец, и я все еще получаю все столбцы для работы. Ура!

Я знаю, что значение dup должно быть одинаковым во всех трех таблицах, но что, если table3 не имеет подходящего значения для dup ? Тогда в первом примере dup будет пустым, и это будет облом.

Еще один совет: если вы хотите иметь более чистый PHP-код, вы можете создать VIEW в базе данных, например

Например:

 CREATE VIEW view_news AS SELECT news.id news_id, user.id user_id, user.name user_name, [ OTHER FIELDS ] FROM news, users WHERE news.user_id = user.id; 

В PHP:

 $sql = "SELECT * FROM view_news"; 

Вы можете сделать что-то вроде

 SELECT news.id as news_id, user.id as user_id .... 

И тогда $row['news_id'] будет идентификатором новостей, а $row['user_id'] будет идентификатором пользователя

@Jason. Вы правы, за исключением того, что php является виновником, а не mysql. Если вы поместите свой JOIN в Mysql Workbench, вы получите три столбца с одинаковым именем (по одному для каждой таблицы), но не с теми же данными (некоторые будут null если эта таблица не соответствует JOIN ).

В php, если вы используете MYSQL_NUM в mysql_fetch_array() вы получите все столбцы. Проблема заключается в том, что вы используете mysql_fetch_array() с MYSQL_ASSOC . Затем внутри этой функции php создает возвращаемое значение следующим образом:

 $row['dup'] = [value from table1] 

и далее …

 $row['dup'] = [value from table2] 

 $row['dup'] = [value from table3] 

Таким образом, вы получите только значение из таблицы3. Проблема в том, что набор результатов из mysql может содержать столбцы с тем же именем, но ассоциативные массивы в php не позволяют дублировать ключи в массивах. Когда данные сохраняются в ассоциативных массивах, в php некоторая информация без потерь теряется …

У меня была такая же проблема с динамическими таблицами. (Таблицы, которые, как предполагается, имеют идентификатор, чтобы иметь возможность присоединиться, но без каких-либо предположений для остальных полей.) В этом случае вы не знаете псевдонимы перед рукой.

В таких случаях вы можете сначала получить имена столбцов таблицы для всех динамических таблиц:

 $tblFields = array_keys($zendDbInstance->describeTable($tableName)); 

Где $ zendDbInstance является экземпляром Zend_Db или вы можете использовать одну из функций здесь, чтобы не полагаться на Zend php pdo: получить имя столбца таблицы

Затем для всех динамических таблиц вы можете получить псевдонимы и использовать $ tableName. * Для тех, для которых вам не нужны псевдонимы:

 $aliases = ""; foreach($tblKeys as $field) $aliases .= $tableName . '.' . $field . ' AS ' . $tableName . '_' . $field . ',' ; $aliases = trim(',', $aliases); 

Вы можете превратить весь этот процесс в одну общую функцию и просто иметь более чистый код или получить более ленивый, если хотите 🙂

Если вам не нравится aliassing, вы также можете просто префикс tablenames.

Таким образом, вы можете лучше автоматизировать генерацию своих запросов. Кроме того, лучше всего не использовать select * (это, очевидно, медленнее, чем просто выбор полей, которые вам нужны. Кроме того, явным образом указываю поля, которые вы хотите иметь.

 SELECT news.id, news.title, news.author, news.posted, users.id, users.name, users.registered FROM news LEFT JOIN users ON news.user = user.id 

Существует два подхода:

1. Использование псевдонимов; в этом методе вы даете новые уникальные имена (ALIAS) различным столбцам, а затем используйте их в поиске PHP.

например.

SQL $ sql = SELECT student_id FEES_LINK, student_class CLASS_LINK from students_fee_tbl ЛЕВЫЙ JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id

PHP $ query = mysql_fetch_assoc ($ sql); // если используется старый подход

$ query = PDO->fetchAll(); // не точный синтаксис, но это текущий подход

 foreach($query as $q){ echo $q['FEES_LINK']; } 

2.

Использование индекса позиции позиции или результатов; в этом случае позиции массива используются для ссылки на дублированные имена столбцов. Поскольку они появляются на разных позициях, номера индексов, которые будут использоваться, всегда уникальны. Однако номера позиционирования индекса начинаются с 0.

например.

$ sql = SELECT student_id, student_class from students_fee_tbl LEFT JOIN student_class_tbl ON students_fee_tbl.student_id = student_class_tbl.student_id

PHP

$ query = mysql_fetch_assoc ($ sql); // если используется старый подход

$ query = PDO-> fetchAll (); // не точный синтаксис, но это текущий подход

 foreach($query as $q){ echo $q[0]; } 

эти две работы.

Надеюсь, поможет. 🙂