sql >> データベース >  >> RDS >> Mysql

SQLの問題:1対多の関係とEAVモデル

    あなたの質問に対する簡単な答えはノーです。MySQLにはあなたが探している結果セットを達成するための簡単な構成はありません。

    しかし、そのようなクエリを注意深く(骨の折れるように)作成することは可能です。ここに例があります、私はあなたがそれを解読することができると信じています。基本的に、返される属性ごとに、選択リストで相関サブクエリを使用しています。

    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
    

    'multi-valued'属性の場合、属性の各インスタンスを個別にプルする必要があります。 (LIMITを使用して、最初のものを取得するか、2番目のものを取得するかなどを指定します。)

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

    ここでは例としてニックネームを使用します。これは、アメリカのサッカークラブには複数のニックネームがあることが多いためです。シカゴファイアーサッカークラブのニックネームは、「The Fire」、「LaMáquinaRoja」、「Men in Red」、「CF97」などです。)

    あなたの質問への答えではありませんが...

    これまで何度も言及したことがありますが、EAVデータベースの実装での作業はどれほど嫌いですか?非常に単純なクエリであるIMOは、潜在的に軽い調光クエリの非常に複雑な獣に変わります。

    各「属性」が別々の列であるテーブルを作成する方がはるかに簡単ではないでしょうか。次に、妥当な結果セットを返すクエリは、より妥当に見えます...

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

    しかし、本当に私を震え上がらせるのは、「より単純な」クエリを有効にするために、一部の開発者がLDQをビューとしてデータベースに「非表示」にする必要があると判断するという見通しです。

    このルートを使用する場合は、このクエリをビューとしてデータベースに保存する必要があるかもしれないという衝動に抵抗してください。



    1. JDBCまたはHibernateを使用して現在のデータベーストランザクションIDを取得するにはどうすればよいですか?

    2. JavaJDBCを使用してMySqlのデータベーススキーマ名のリストを取得する方法

    3. MySqlは、ある行から別の行に値をコピーします

    4. ZendFrameworkでプリペアドステートメントを使用する方法