Éste parece ser un problema simple, pero no puedo hacer que funcione en un solo seleccione o anidado seleccione. Recupere los autores y (si los hay) asesores de un documento (artículo) en una fila.Subselección de columna múltiple en mysql 5 (5.1.42)
I para explicar el problema, aquí están las dos tablas de datos (pseudo)
papers (id, title, c_year)
persons (id, firstname, lastname)
además de una mesa de enlace w/un atributo adicional (pseudo):
paper_person_roles(
paper_id
person_id
act_role ENUM ('AUTHOR', 'ADVISER')
)
Esto es, básicamente, una lista de documentos escritos (tabla: documentos) y una lista del personal y/o estudiantes (tabla: personas)
un artículo tiene mis (1, N) autores.
Un artículo puede tener asesores (0, N).
Una persona puede estar en el rol 'AUTOR' o 'ASESOR' (pero no al mismo tiempo).
La aplicación pone finalmente a cabo filas de la tabla que contiene los entradas siguientes:
TH: || Paper_ID | Author(s) | Title | Adviser(s) | TD: || 21334 |John Doe, Jeff Tucker|Why the moon looks yellow|Brown, Rayleigh| ...
Mi primer acercamiento fue como:
seleccionar/extraer una lista completa de los artículos en la aplicación, por ejemplo.
SELECT
q.id, q.title
FROM
papers AS q
ORDER BY
q.c_year
y guarde los resultados de la consulta en una matriz (en la aplicación). Después de este paso , recorra la matriz de la información devuelta y recupere los autores y los asesores (si corresponde), mediante una declaración preparada (? Es la identificación del documento) de la tabla de enlace como
APPLICATION_LOOP(paper_ids in array)
SELECT
p.lastname, p.firstname, r.act_role
FROM
persons AS p, paper_person_roles AS r
WHERE
p.id=r.person_id AND r.paper_id = ?
# The application does further processing from here (pseudo):
foreach record from resulting records
if record.act_role eq 'AUTHOR' then join to author_column
if record.act_role eq 'ADVISER' then join to avdiser_column
end
print id, author_column, title, adviser_column
APPLICATION_LOOP
Esto funciona hasta ahora y le da al salida deseada. ¿Sería necesario devolver el cálculo al DB?
No soy muy competente en SQL no trivial y no puedo encontrar una solución con una sola llamada de selección (combinada o anidada). I intenté algo. como
SELECT
q.title
(CONCAT_WS(' ',
(SELECT p.firstname, p.lastname AS aunames
FROM persons AS p, paper_person_roles AS r
WHERE q.id=r.paper_id AND r.act_role='AUTHOR')
)
) AS aulist
FROM
papers AS q, persons AS p, paper_person_roles AS r
en varias variaciones, pero no hubo suerte ...
¿Tal vez hay alguna posibilidad?
Gracias de antemano
de fondo redondo
Peter, su respuesta es increíble. Este realmente funciona, solo tuve que eliminar el CONCAT interno (..) del asesor unido para obtener exactamente el resultado deseado (apellido de los asesores solamente). La base de datos no es muy grande (hasta ahora), por lo que el tiempo de respuesta en estas uniones múltiples es inferior a 1/10'th de segundo. Intentaré imaginar cómo insertar un espacio en blanco si no se devuelve ningún asesor (se devuelve el campo NULO). ¡Muchas gracias! –
De nada :) Para insertar un espacio en blanco en lugar de 'NULL', puede usar' COALESCE (p_aut.aut_name, '') ' –
OK, aprendí mucho de su respuesta. Ahora tengo algo de confianza en poner atributos NULL-able en las tablas (para los que no existen primero- y nombres intermedios), porque solo entonces las funciones Concat/Group_Concat arrojarán resultados útiles sin más posprocesamiento. BTW. Probé la consulta temporalmente en el entorno de producción y el tiempo de respuesta se redujo a la mitad en comparación con la anterior solución "procedimental" . Gracias y buenas noches –