0

動的アプリケーションを構築しています。私は3つのテーブルを持っています:(EAVモデルスタイル)

  1. アイテム (アイテム ID、アイテム名)
  2. フィールド (FieldId、FieldName)
  3. フィールド値 (ItemID、FieldId、Value)

FieldId=4 が TRUE に等しいすべてのアイテムから 20 レコードを取得するための SINGLE クエリの書き方を教えてください。

期待される結果 :

Columns =>  ItemID | Name  | Field1 | Field2 |  Field3  
Each Row=>  ItemId | ItemName| Value1 | Value2 | Value3

重要な懸念事項:

  1. アイテムごとのフィールド数は不明
  2. 1 つのクエリを作成するために 1 つ必要です。
  3. クエリは 100K レコードに対して実行されるため、パフォーマンスが懸念されます。
  4. MySQL 5.0 を使用しているため、MYSQL のソリューションが必要です

上記のクエリがまったく不可能な場合、テーブルを非正規化する必要がありますか? 何かアドバイス ?

4

1 に答える 1

1

EAV 設計非正規化されています。つまり、非リレーショナル設計です。EAV 設計を使用するように導く正規化のルールはありません。

SQL では、クエリを記述するときに列を知っている必要があり、結果セットのすべての行に同じ列が含まれている必要があります。EAV では、アイテムごとにいくつのフィールドがあるかわからない場合の唯一の解決策は、それらを列ではなく行としてフェッチすることです。

SELECT i.ItemID, i.ItemName, f.FieldName, v.Value
FROM Items i
JOIN FieldsValues v4 ON (v4.ItemID, v4.FieldID, v4.Value) = (i.ItemID, 4, TRUE)
JOIN FieldsValues v ON i.ItemID = v.ItemID
JOIN Fields f ON v.FieldID = f.FieldID;

アプリケーションで行を処理する必要があります。たとえば、PHP の場合:

<?php

$pdo = new PDO(...);
$sql = "...above query...";

$collection = array();

foreach ($pdo->query($sql) as $row) {
  $id = $row["ItemID"];
  if (!array_key_exists($id, $collection)) {
    $collection[$id] = new stdClass();
    $collection[$id]->Name = $row["ItemName"];
  }
  $collection[$id]->$row["FieldName"] = $row["Value"];
}

これでオブジェクトの配列ができました。各オブジェクトはデータベースの項目に対応しています。各オブジェクトには、それぞれのフィールド セットがあります。

于 2010-07-22T01:35:38.347 に答える