数据库EAV模型,根据搜索记录列表

时间:2010-05-16 11:20:51

标签: mysql entity-attribute-value nor

我正在构建一个动态应用程序。 我有三张桌子:( EAV模型)

  1. 项目(ItemId,ItemName)
  2. 字段(FieldId,FieldName)
  3. 字段值(ItemID,FieldId,Value)
  4. 您能告诉我如何编写SINGLE查询以从FieldId = 4等于TRUE的所有项目中获取20条记录。

    预期结果:

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

    重要问题:

    1. 每个项目的字段数未知
    2. 我需要一个人写一个查询。
    3. 查询将在100K记录上运行,因此性能受到关注。
    4. 我使用的是MySQL 5.0,因此需要MYSQL的解决方案
    5. 如果上面的查询根本不可能,我应该对表进行非规范化吗?有什么建议吗?

1 个答案:

答案 0 :(得分: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"];
}

现在您有一个对象数组,每个对象对应于数据库中的一个项目。每个对象都有各自的字段集。