Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Problema SQL:relacionamento um para muitos e modelo EAV


A resposta curta para sua pergunta é não, não há uma construção simples no MySQL para alcançar o conjunto de resultados que você está procurando.

Mas é possível elaborar cuidadosamente (minuciosamente) essa consulta. Aqui está um exemplo, eu acredito que você será capaz de decifrá-lo. Basicamente, estou usando subconsultas correlacionadas na lista de seleção, para cada atributo que desejo retornar.
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 atributos 'multivalorados', você teria que puxar cada instância do atributo separadamente. (Use o LIMIT para especificar se você está recuperando o primeiro, o 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

Eu uso apelido como exemplo aqui, porque os clubes de futebol americano frequentemente têm mais de um apelido, por exemplo, Chicago Fire Soccer Club tem apelidos:'The Fire', 'La Máquina Roja', 'Men in Red', 'CF97', et al.)

NÃO RESPONDE SUA PERGUNTA, MAS...

Já mencionei várias vezes antes, o quanto eu não gosto de trabalhar com implementações de banco de dados EAV? O que o IMO deveria ser uma consulta muito simples se transforma em uma besta excessivamente complicada de uma consulta de escurecimento potencialmente leve.

Não seria muito mais simples criar uma tabela onde cada "atributo" fosse uma coluna separada? Em seguida, as consultas para retornar conjuntos de resultados razoáveis ​​​​pareceriam mais razoáveis ​​...
SELECT id, name, nickname, city, captain, f_number, ... FROM team

Mas o que realmente me faz estremecer é a perspectiva de algum desenvolvedor decidir que o LDQ deve ser "escondido" no banco de dados como uma view, para habilitar a consulta "mais simples".

Se você seguir esse caminho, POR FAVOR, POR FAVOR, resista a qualquer desejo que você possa ter de armazenar essa consulta no banco de dados como uma visualização.