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


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

новости ('id' - идентификатор новости,' user ' - идентификатор пользователя автора)

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

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

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

обновление: спасибо всем за быстрые ответы. Псевдонимы кажутся лучшими решение.

9 68

9 ответов:

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

$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 будет значение из table1.

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

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

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

например:

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: получить имя столбца a таблица

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

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

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

Если вы не чувствуете, как алиасинг вы также можете просто префикс имена таблиц.

таким образом, вы можете лучше автоматизировать генерацию запросов. Кроме того, лучше всего не использовать 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. Использование псевдонимов; в этом методе вы даете новые уникальные имена (псевдонимы) различным столбцам, а затем используете их в извлечении PHP.

например.

SQL $среда SQL = выберите student_id FEES_LINK, student_class CLASS_LINK от students_fee_tbl левое соединение student_class_tbl на 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.

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

например.

$sql = SELECT student_id, student_class из studentsfee_tbl слева присоединяется к student_class_tbl на studentsfee_tbl.student_id=student_class_tbl.student_id

PHP

$query = mysql_fetch_assoc($sql);//при использовании старого подхода

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

foreach($query as $q){

    echo $q[0];

}

две работы.

надеюсь, что это помогает. :)