sql >> Base de Datos >  >> RDS >> Mysql

Problema de SQL:relación de uno a muchos y modelo EAV

La respuesta corta a su pregunta es no, no existe una construcción simple en MySQL para lograr el conjunto de resultados que está buscando.

Pero es posible elaborar con cuidado (concienzudamente) una consulta de este tipo. Aquí hay un ejemplo, confío en que usted será capaz de descifrarlo. Básicamente, estoy usando subconsultas correlacionadas en la lista de selección, para cada atributo que quiero devolver.

SELECT t.id
     , t.name
     , t.nickname

     , ( SELECT v1.attribute_value 
           FROM team_information v1 
           JOIN attributes a1
             ON a1.id = v1.attribute_id AND a1.attribute_name = 'city'
          WHERE v1.team_id = t.id ORDER BY 1 LIMIT 1
       ) AS city

     , ( SELECT v2.attribute_value
           FROM team_information v2 JOIN attributes a2
             ON a2.id = v2.attribute_id AND a2.attribute_name = 'captain'
          WHERE v2.team_id = t.id ORDER BY 1 LIMIT 1
       ) AS captain

     , ( SELECT v3.attribute_value
           FROM team_information v3 JOIN attributes a3
             ON a3.id = v3.attribute_id AND a3.attribute_name = 'f_number'
          WHERE v3.team_id = t.id ORDER BY 1 LIMIT 1
       ) AS f_number

  FROM teams t
 ORDER BY t.id

Para los atributos de "valores múltiples", tendría que extraer cada instancia del atributo por separado. (Use LIMIT para especificar si está recuperando el primero, el segundo, etc.)

     , ( SELECT v4.attribute_value
           FROM team_information v4 JOIN attributes a4
             ON a4.id = v4.attribute_id AND a4.attribute_name = 'nickname'
          WHERE v4.team_id = t.id ORDER BY 1 LIMIT 0,1
       ) AS nickname_1st

     , ( SELECT v5.attribute_value
           FROM team_information v5 JOIN attributes a5
             ON a5.id = v5.attribute_id AND a5.attribute_name = 'nickname'
          WHERE v5.team_id = t.id ORDER BY 1 LIMIT 1,1
       ) AS nickname_2nd

     , ( SELECT v6.attribute_value
           FROM team_information v6 JOIN attributes a6
             ON a6.id = v6.attribute_id AND a6.attribute_name = 'nickname'
          WHERE v6.team_id = t.id ORDER BY 1 LIMIT 2,1
       ) AS nickname_3rd

Utilizo el apodo como ejemplo aquí, porque los clubes de fútbol estadounidenses suelen tener más de un apodo, p. Chicago Fire Soccer Club tiene apodos:'The Fire', 'La Máquina Roja', 'Men in Red', 'CF97', et al.)

NO ES UNA RESPUESTA A SU PREGUNTA, PERO...

¿He mencionado en numerosas ocasiones lo mucho que me desagrada trabajar con implementaciones de bases de datos EAV? Lo que en mi opinión debería ser una consulta muy simple se convierte en una bestia demasiado complicada de una consulta de atenuación de la luz potencial.

¿No sería mucho más simple crear una tabla donde cada "atributo" sea una columna separada? Entonces las consultas para devolver conjuntos de resultados razonables parecerían más razonables...

SELECT id, name, nickname, city, captain, f_number, ... FROM team

Pero lo que realmente me estremece es la posibilidad de que algún desarrollador decida que el LDQ debería estar "oculto" en la base de datos como una vista, para habilitar la consulta "más simple".

Si sigue esta ruta, POR FAVOR, POR FAVOR, resista cualquier tentación que pueda tener de almacenar esta consulta en la base de datos como una vista.