Mysql
 sql >> Database >  >> RDS >> Mysql

Problema SQL:relazione uno a molti e modello EAV

La risposta breve alla tua domanda è no, non esiste un semplice costrutto in MySQL per ottenere il set di risultati che stai cercando.

Ma è possibile creare con attenzione (scrupolosamente) una tale query. Ecco un esempio, spero che sarai in grado di decifrarlo. Fondamentalmente, sto usando sottoquery correlate nell'elenco di selezione, per ogni attributo che voglio restituire.

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

Per gli attributi "multivalore", dovresti estrarre ogni istanza dell'attributo separatamente. (Utilizza il LIMIT per specificare se stai recuperando il primo, il secondo, ecc.)

     , ( 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

Uso il soprannome come esempio qui, perché le squadre di calcio americane hanno spesso più di un soprannome, ad es. Il Chicago Fire Soccer Club ha soprannomi:'The Fire', 'La Máquina Roja', 'Men in Red', 'CF97', et al.)

NON UNA RISPOSTA ALLA TUA DOMANDA, MA...

Ho già menzionato numerose volte quanto non mi piace lavorare con le implementazioni di database EAV? Quale dovrebbe essere una query molto semplice IMO si trasforma in una bestia eccessivamente complicata di una query potenzialmente attenuazione della luce.

Non sarebbe molto più semplice creare una tabella in cui ogni "attributo" è una colonna separata? Quindi le query per restituire set di risultati ragionevoli sembrerebbero più ragionevoli...

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

Ma ciò che mi fa davvero rabbrividire è la prospettiva che qualche sviluppatore decida che l'LDQ debba essere "nascosto" nel database come vista, per abilitare la query "più semplice".

Se segui questa strada, PER FAVORE, PER FAVORE, PER FAVORE, resisti a qualsiasi impulso che potresti dover archiviare questa query nel database come vista.