web-dev-qa-db-fra.com

PHP & MYSQL: Comment résoudre les noms de colonnes ambigus dans l'opération JOIN?

J'ai deux tables dans ma base de données:

NEWS ('id' - l'identifiant d'actualités, 'utilisateur' - l'identifiant d'utilisateur de l'auteur)

USERS ('id' - l'identifiant de l'utilisateur)

Je veux faire un SELECT * FROM news JOIN users ON news.user = user.id, Maintenant, quand je reçois les résultats dans PHP c'est quelque chose comme:

$row = mysql_fetch_array($result), et obtenez les noms de colonne par $row['column-name'] ... comment puis-je obtenir l'ID de news et l'ID utilisateur, ayant le même nom de colonne?

MISE À JOUR: Merci à tous pour les réponses rapides. Les alias semblent la meilleure solution.

71
Dan Burzo

Vous pouvez définir des alias pour les colonnes que vous sélectionnez:

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

Vous pouvez soit utiliser les index numériques ($row[0]) ou mieux, utilisez AS dans MySQL:

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

40
Greg

Je viens de comprendre cela. C'est probablement une mauvaise pratique, mais cela a fonctionné pour moi dans ce cas.

Je suis un des paresseux qui ne veut pas alias ou écrire chaque nom de colonne avec un préfixe de table.

Vous pouvez sélectionner toutes les colonnes d'une table spécifique en utilisant table_name.* dans votre déclaration select.

Lorsque vous avez dupliqué les noms de colonnes, mysql écrase du premier au dernier. Les données du premier nom de colonne dupliqué seront écrasées lorsqu’il rencontrera à nouveau ce nom de colonne. Ainsi, le nom de colonne dupliqué qui vient en dernier gagne.

Si je joins 3 tables, chacune contenant un nom de colonne dupliqué, l'ordre des tables dans l'instruction select déterminera les données que j'obtiens pour la colonne dupliquée.

Exemple:

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

Dans l'exemple ci-dessus, la valeur de dup que j'obtiendra sera de table3.

Et si je veux que dup soit la valeur de table1?

Alors je dois faire ceci:

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

À présent, table1 vient en dernier, donc la valeur de dup sera celle de table1.

J'ai obtenu la valeur que je recherchais pour dup sans avoir à écrire toutes les colonnes freaking et je dois toujours utiliser toutes les colonnes. Yay!

Je sais que la valeur de dup devrait être la même dans les 3 tables, mais que se passe-t-il si table3 n'a pas de valeur correspondante pour dup? Ensuite, dup serait vide dans le premier exemple, ce qui serait décevant.

21
Eab

Autre astuce: si vous voulez avoir un code plus propre PHP, vous pouvez créer une VUE dans la base de données, par exemple.

Par exemple:

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;

En PHP:

$sql = "SELECT * FROM view_news";
9
Dirk

@ Jason. Vous avez raison, sauf que php est le coupable et non mysql. Si vous mettez votre JOIN dans Mysql Workbench, vous obtiendrez trois colonnes avec le même nom exact (une pour chaque table) mais pas avec les mêmes données (certaines seront null si cette table ne contient pas correspond pour le JOIN).

En php, si vous utilisez MYSQL_NUM Dans mysql_fetch_array(), vous obtiendrez toutes les colonnes. Le problème est lorsque vous utilisez mysql_fetch_array() avec MYSQL_ASSOC. Ensuite, dans cette fonction, php construit la valeur de retour comme suit:

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

et plus tard ...

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

...

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

Donc, vous obtiendrez seulement la valeur de table3. Le problème est qu'un jeu de résultats de mysql peut contenir des colonnes portant le même nom, mais les tableaux associatifs en php n'autorisent pas les clés en double dans les tableaux. Lorsque les données sont enregistrées dans des tableaux associatifs, en php, certaines informations sont perdues silencieusement ...

8
GoTo

Vous pouvez faire quelque chose comme

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

Et alors $row['news_id'] sera le nouvel identifiant et $row['user_id'] sera l'identifiant de l'utilisateur

8
Paolo Bergantino

J'ai eu le même problème avec les tables dynamiques. (Les tables supposées avoir un identifiant pour pouvoir se joindre, mais sans aucune hypothèse pour le reste des champs.) Dans ce cas, vous ne connaissez pas les alias à l'avance.

Dans ce cas, vous pouvez d’abord obtenir les noms de colonne de la table pour toutes les tables dynamiques:

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

Où $ zendDbInstance est une instance de Zend_Db ou vous pouvez utiliser l'une des fonctions ici pour ne pas compter sur Zend php pdo: obtenir le nom des colonnes d'une table

Ensuite, pour toutes les tables dynamiques, vous pouvez obtenir les alias et utiliser $ nomTable. * Pour ceux dont vous n'avez pas besoin:

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

Vous pouvez intégrer tout ce processus dans une fonction générique et simplement avoir un code plus propre ou être plus paresseux si vous le souhaitez :)

2
haknick

Si vous ne souhaitez pas rester aliassant, vous pouvez également préfixer les noms de fichiers.

De cette façon, vous pouvez mieux automatiser la génération de vos requêtes. En outre, il est recommandé de ne pas utiliser select * (cela est évidemment plus lent que de simplement sélectionner les champs que vous besoin De plus, nommez explicitement les champs que vous souhaitez avoir.

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
SchizoDuckie