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

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

НОВОСТИ ('id' - идентификатор новостей, 'пользователь' - идентификатор пользователя автора)

ПОЛЬЗОВАТЕЛИ ('id' - идентификатор пользователя)

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

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

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

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

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

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

Вы можете выбрать все столбцы из конкретной таблицы, используя 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 будет пустым в первом примере, и это будет облом.

Ответ 4

Еще один совет: если вы хотите иметь более чистый 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";

Ответ 5

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

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

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

Ответ 6

@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 некоторая информация бесшумно теряется...

Ответ 7

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

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

$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);

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

Ответ 8

Если вам не нравится 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

Ответ 9

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

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

например.

SQL $ sql = SELECT student_id FEES_LINK, student_class CLASS_LINK from students_fee_tbl ЛЕВЫЙ ПРИСОЕДИНЕНИЕ 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];

}

две работы.

Надеюсь, это поможет.:)