1

我正在使用这样的数据库设置:

  entity field       value
   1      start_date  June 1, 2010
   1      end_date    August 30, 2010
   1      artist      some name

我想查询已经开始但未结束的艺术家名称“某个名称”的所有实体。

我想出了这样的事情:

SELECT start.entity
FROM field_values AS `start`
  INNER JOIN field_values AS `end`
  INNER JOIN field_values AS `artist`
WHERE 
  (start.field = 'start_date' AND end.field = 'end_date' AND artist.field='artist')  AND 
  (STR_TO_DATE(start.value, '%M %d, %Y') < NOW() AND 
   STR_TO_DATE(end.value, '%M %d, %Y') > NOW())  AND 
  artist.value="some artist";

但这并没有让我觉得非常有效。有更好的方法吗?

4

2 回答 2

1

为了清楚起见,您可以将连接子句项放在连接子句中,但就查询优化而言,这几乎是这样做的方法。

您可以考虑将查询重写为以下内容:

SELECT start.entity
FROM entity
  JOIN field_values AS start
    ON entity.id = start.entity AND start.field = 'start_date'
  INNER JOIN field_values AS end
    ON entity.id = end.entity AND end.field = 'end_date'
  INNER JOIN field_values AS artist
    ON entity.id = artist.entity AND artist.field = 'artist'
WHERE STR_TO_DATE(start.value, '%M %d, %Y') < NOW()
  AND STR_TO_DATE(end.value, '%M %d, %Y') > NOW()
  AND artist.value="some artist"
;

您还可以规范化该字段以节省一点空间(假设该字段不是枚举)

于 2010-08-03T23:46:32.213 回答
1

虽然 EAV 有它的位置,但您已经有 3 个有保证的属性名称(当您正在搜索它时,我假设很多实体共享这些属性)。闻起来像 EAV 的非候选者,或者可能进入其单独表中的属性的可能组合,这可能会像您喜欢的那样artistdates (id,artist,start,end)链接到 EAV 表中。E=<whatever>,A=artistdate_id,V=<artistdate_id>

EAV 的强大之处在于那些实际存在的属性不一致的情况,通常只通过 entity-id 或属性的存在(可能与值结合)来查询。一旦您正在寻找属性组合,性能就会受到影响,问题是这些属性是否应该单独存在于 EAV 结构中,或者它们应该被拆分成一个“传统的”基于行的表。

于 2010-08-03T23:58:59.473 回答