sql >> Databasteknik >  >> RDS >> Mysql

SQL-problem:en till många relation och EAV-modell

Det korta svaret på din fråga är nej, det finns ingen enkel konstruktion i MySQL för att uppnå det resultat du letar efter.

Men det är möjligt att noggrant (mösamt) skapa en sådan fråga. Här är ett exempel, jag litar på att du kommer att kunna tyda det. I grund och botten använder jag korrelerade underfrågor i urvalslistan, för varje attribut jag vill ha tillbaka.

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

För "multi-valued" attribut måste du dra varje instans av attributet separat. (Använd LIMIT för att ange om du hämtar den första, den andra, 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

Jag använder smeknamn som exempel här, eftersom amerikanska fotbollsklubbar ofta har mer än ett smeknamn, t.ex. Chicago Fire Soccer Club har smeknamn:'The Fire', 'La Máquina Roja', 'Men in Red', 'CF97', et al.)

INTE ETT SVAR PÅ DIN FRÅGA, MEN ...

Har jag nämnt många gånger tidigare, hur mycket jag ogillar att arbeta med EAV-databasimplementeringar? Vad ska IMO vara en mycket enkel fråga förvandlas till en alltför komplicerad beast av en potentiellt lätt dimningsfråga.

Skulle det inte vara mycket enklare att skapa en tabell där varje "attribut" är en separat kolumn? Då skulle frågor för att returnera rimliga resultatuppsättningar se mer rimliga ut...

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

Men det som verkligen får mig att rysa är möjligheten att någon utvecklare kommer att besluta att LDQ ska "gömmas" i databasen som en vy, för att möjliggöra den "enklare" frågan.

Om du går den här vägen, SNÄLLA SNÄLLA SNÄLLA SNÄLLA motstå varje uppmaning du kan behöva att lagra denna fråga i databasen som en vy.



  1. Hur återställer jag postgresql 9.2 standardanvändarlösenordet (vanligtvis 'postgres') på mac os x 10.8.2?

  2. MySQL INSERT I DÄR INTE FINNS

  3. Lär dig grundläggande dataanalys med SQL-fönsterfunktioner

  4. Golang, mysql:Fel 1040:För många anslutningar