promocionado - PHP y MYSQL: ¿cómo resolver nombres de columnas ambiguos en la operación JOIN?
inner join (9)
@Jason. Estás en lo correcto, excepto que php es el culpable y no mysql. Si coloca su JOIN
en Mysql Workbench, obtendrá tres columnas con el mismo nombre (una para cada tabla) pero no con los mismos datos (algunas serán null
si esa tabla no concuerda con JOIN
).
En php si usas MYSQL_NUM
en mysql_fetch_array()
obtendrás todas las columnas. El problema es cuando usas mysql_fetch_array()
con MYSQL_ASSOC
. Entonces, dentro de esa función, php está construyendo el valor de retorno así:
$row[''dup''] = [value from table1]
y luego ...
$row[''dup''] = [value from table2]
...
$row[''dup''] = [value from table3]
Por lo tanto, obtendrá solo el valor de la tabla3. El problema es que un conjunto de resultados de mysql puede contener columnas con el mismo nombre, pero las matrices asociativas en php no permiten claves duplicadas en las matrices. Cuando los datos se guardan en matrices asociativas, en php, parte de la información se pierde silenciosamente ...
Tengo dos tablas en mi base de datos:
NOTICIAS (''id'' - la ID de noticias, ''usuario'' - la identificación de usuario del autor)
USUARIOS (''id'' - la identificación del usuario)
Quiero hacer SELECT * FROM news JOIN users ON news.user = user.id
, ahora cuando obtengo los resultados en PHP es algo así como:
$row = mysql_fetch_array($result)
, y obtener nombres de columna por $row[''column-name'']
... ¿cómo obtengo la ID de la noticia y la ID del usuario, con el mismo nombre de columna?
ACTUALIZACIÓN: Gracias a todos por las respuestas rápidas. Los alias parecen ser la mejor solución.
Hay dos enfoques:
1. Usar alias; en este método, usted otorga nuevos nombres únicos (ALIAS) a las diversas columnas y luego los utiliza en la recuperación de PHP.
p.ej.
SQL $ sql = SELECCIONE student_id FEES_LINK, student_class CLASS_LINK de 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); // si usa el viejo enfoque
$ query = PDO->fetchAll();
// sin sintaxis exacta, pero este es el enfoque actual
foreach($query as $q){
echo $q[''FEES_LINK''];
}
2.
Usar posición de posición o índice de columna de conjunto de resultados; en esto, las posiciones de la matriz se utilizan para hacer referencia a los nombres de columna duplicados. Como aparecen en diferentes posiciones, los números de índice que se usarán siempre son únicos. Sin embargo, los números de posicionamiento del índice comienzan en 0.
p.ej.
$ sql = SELECCIONE 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); // si se usa el viejo enfoque
$ query = PDO-> fetchAll (); // sin sintaxis exacta, pero este es el enfoque actual
foreach($query as $q){
echo $q[0];
}
las dos obras.
Espero eso ayude. :)
Me di cuenta de esto. Probablemente sea una mala práctica, pero funcionó en este caso.
Soy una de las personas perezosas que no quiere alias ni escribir cada nombre de columna con un prefijo de tabla.
Puede seleccionar todas las columnas de una tabla específica usando table_name.*
En su instrucción de selección.
Cuando haya duplicado los nombres de las columnas, mysql sobrescribirá de principio a fin. Los datos del primer nombre de columna duplicado se sobrescribirán cuando encuentre ese nombre de columna nuevamente. Por lo tanto, el nombre de la columna duplicada que aparece en último lugar gana.
Si me estoy uniendo a 3 tablas, cada una con un nombre de columna duplicado, el orden de las tablas en la declaración de selección determinará qué datos obtendré para la columna duplicada.
Ejemplo:
SELECT table1.* , table2.* , table3.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup;
En el ejemplo anterior, el valor de dup
que obtengo será de la table3
.
¿Qué dup
si quiero que dup
sea el valor de table1
?
Entonces necesito hacer esto:
SELECT table3.* , table2.* , table1.* FROM table1 LEFT JOIN table2 ON table1.dup = table2.dup LEFT JOIN table3 ON table2.dup = table3.dup;
Ahora, la table1
es la última, por lo que el valor de dup
será el valor de la tabla1.
Obtuve el valor que quería para dup
sin tener que escribir cada columna volátil y todavía consigo todas las columnas para trabajar. ¡Hurra!
Sé que el valor de dup
debe ser el mismo en las 3 tablas, pero ¿y si la table3
no tiene un valor coincidente para dup
? Entonces dup
estaría en blanco en el primer ejemplo, y eso sería un fastidio.
Otro consejo: si quieres tener un código PHP más limpio, puedes crear una VISTA en la base de datos, por ej.
Por ejemplo:
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";
Puede establecer alias para las columnas que está seleccionando:
$query = ''SELECT news.id AS newsId, user.id AS userId, [OTHER FIELDS HERE] FROM news JOIN users ON news.user = user.id''
Puede usar los índices numéricos ( $row[0]
) o mejor, use AS
en MySQL:
SELECT *, user.id AS user_id FROM ...
Puedes hacer algo como
SELECT news.id as news_id, user.id as user_id ....
Y luego $row[''news_id'']
será la identificación de noticias y $row[''user_id'']
será la identificación de usuario
Si no tiene ganas de aliassing, también puede prefijar los nombres de las tablas.
De esta forma puede automatizar mejor la generación de sus consultas. Además, es una buena práctica no usar select * (obviamente es más lento que simplemente seleccionar los campos que necesita Además, solo nombre explícitamente los campos que desea tener.
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
Tuve el mismo problema con las tablas dinámicas. (Tablas que se supone que tienen un ID para poder unirse, pero sin ninguna suposición para el resto de los campos). En este caso, no conoce los alias de antemano.
En tales casos, primero puede obtener los nombres de columna de la tabla para todas las tablas dinámicas:
$tblFields = array_keys($zendDbInstance->describeTable($tableName));
Donde $ zendDbInstance es una instancia de Zend_Db o puede usar una de las funciones aquí para no confiar en Zend php pdo: obtener el nombre de las columnas de una tabla
Luego, para todas las tablas dinámicas, puede obtener los alias y usar $ tableName. * Para los que no necesita alias:
$aliases = "";
foreach($tblKeys as $field)
$aliases .= $tableName . ''.'' . $field . '' AS '' . $tableName . ''_'' . $field . '','' ;
$aliases = trim('','', $aliases);
Puede envolver todo este proceso en una función genérica y solo tener un código más limpio o conseguir más perezoso si lo desea :)