MySQL - Dos claves foráneas apuntando a la misma tabla

Apuntar dos claves foráneas a una misma tabla es un caso límite. Si es posible, es mejor que modifique la estructura de su base de datos. De lo contrario, tendrá que editar el código de su lista READ.


Acerca de las estructuras que utilizan dos uniones a una sola mesa

Utilizar dos uniones a la misma tabla es una estructura perfectamente lógica en algunos casos, pero este tipo de estructura suele ser poco práctica en su uso.

Pongamos un ejemplo sencillo:

MySQL two joins to the same table example
Ejemplo de una tabla MySQL con dos uniones a la misma tabla

Para seleccionar registros de la tabla de proyectos necesitamos utilizar este tipo de consulta:

SELECT
    projects.name,
    manager.name AS manager_name,
    manager.firstname AS manager_firstname,
    employee.name AS employee_name,
    employee.firstname AS employee_firstname
FROM
    projects
    LEFT JOIN persons AS manager ON projects.manager_id = manager.id
    LEFT JOIN persons AS employee ON projects.employee_id = employee.id

Esta consulta utiliza alias tanto en los campos de la tabla de personas como en el nombre de la propia tabla, ya que se consulta dos veces (una por cada unión).

Esta no es la solución adecuada. PHPCG utiliza un sistema de filtro avanzado que le permite buscar y filtrar registros en sus listas, pero no admite el uso de alias para las tablas.

Existen dos soluciones alternativas.


Primera solución: cambie la estructura de su base de datos

En el ejemplo anterior, la tabla de personas agrupa dos entidades diferentes en la misma tabla: directivos y empleados.

Esto no es una buena idea. Siempre es mejor crear una tabla para cada tipo de datos (cada entidad).

MySQL two joins to two distinct tables
Ejemplo de una tabla MySQL con dos uniones a dos tablas distintas

Segunda solución: editar manualmente la consulta SQL de la lista READ

Tomemos una estructura ligeramente diferente:

MySQL two joins to the same table example 2
Tabla MySQL con dos uniones a la misma tabla - Ejemplo 2

En este segundo caso, la tabla de proyectos hace referencia a dos empleados.
No sería coherente crear dos tablas para los empleados, ya que éstos representan una entidad única.

La solución es editar la clase PHP que crea los empleados y sustituir la consulta generada por el generador por dos consultas separadas.

He aquí cómo hacerlo:

  1. Abra el archivo admin/class/crud/Projects. php en su editor de código
    (sustituya Proyectos por el nombre de su tabla)
  2. Busque la consulta en el código y elimine los campos y el join que hacen referencia al segundo join.
    La parte join de la consulta comienza con $this->join_query = ' LEFT JOIN ...' y la parte fields comienza con $qry_start = 'SELECT ...'
  3. Encuentre la parte de código donde se registran los registros. Comienza con while (!$db->endOfSeek()) { ...
  4. En este bucle, elimine los resultados que hagan referencia a la segunda unión
  5. Después del bucle, añada uno nuevo para realizar un bucle dentro de todos los registros y obtener los registros de la segunda unión.
    En nuestro ejemplo sería:
    for ($i=0; $i < $this->recuento_registros; $i++) { $qry = 'SELECT `empleados`.`id` COMO `id_empleados`, `nombre`.empleados` COMO `nombre_empleados` FROM proyectos LEFT JOIN `empleados` ON `proyectos`.`id_2`=`id`.empleados` WHERE proyectos.id = ' . $this->id[$i] . ' LIMIT 1'; $db = new DB(); $db->query($qry); $db_count = $db->rowCount(); if (!empty($db_count)) { $row = $db->fetch(); $this->employees2_id[] = $row->employees_id . '[|]' . $row->employees_name; } else { $this->employees2_id[] = ''; } }

Después de realizar estos cambios personalizados en el código, si más tarde tiene que reconstruir su lista READ desde el generador no olvide que dispone de la herramienta de comparación de archivos:
Regenerar lista y formularios que han sido personalizados (Cómo utilizar la herramienta de comparación de archivos del generador CRUD)

Por supuesto, esta solución requiere algunos conocimientos de codificación, si necesita ayuda póngase en contacto con nosotros y haremos todo lo posible.

Página principal del tutorial PHP CRUD