PHP & MYSQL: как разрешить неоднозначные имена столбцов в операции JOIN? - PullRequest
71 голосов
/ 10 января 2009

В моей базе данных две таблицы:

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

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

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

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

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

Ответы [ 9 ]

113 голосов
/ 10 января 2009

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

$query = 'SELECT news.id AS newsId, user.id AS userId, [OTHER FIELDS HERE] FROM news JOIN users ON news.user = user.id'
40 голосов
/ 10 января 2009

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

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

21 голосов
/ 14 ноября 2009

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

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

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

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

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

Пример:

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 должно быть одинаковым во всех 3 таблицах, но что если table3 не имеет соответствующего значения для dup? Тогда dup будет пустым в первом примере, и это будет облом.

9 голосов
/ 14 октября 2011

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

@ Джейсон. Вы правы, за исключением того, что 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 часть информации молча теряется ...

8 голосов
/ 10 января 2009

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

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

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

2 голосов
/ 03 июня 2011

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

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

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

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

1 голос
/ 11 января 2009

Если вы не хотите создавать псевдонимы, вы можете просто добавить префикс к именам таблиц.

Таким образом, вы можете лучше автоматизировать генерацию ваших запросов. Кроме того, лучше не использовать 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
0 голосов
/ 18 января 2017

Есть два подхода:

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

например.

SQL $ sql = ВЫБЕРИТЬ student_id FEES_LINK, студент_класса CLASS_LINK из student_fee_tbl ВЛЕВО СОЕДИНИТЬ student_class_tbl ON student_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 = ВЫБЕРИТЬ student_id, student_class из 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[0];

}

две работы.

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

...