2010-08-03 2 views
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"; 

Но это не поражает меня как невероятно эффективным. Есть ли лучший подход к этому?

+0

Наиболее эффективным решением является преобразование этих атрибутов в столбцы и устранение EAV. :) – Thomas

+0

@Thomas Как я мог бы это сделать – blockhead

+2

Чтобы расширить то, что говорит Томас: Эта идея EAV не бесполезна, но вы не хотите использовать ее для атрибутов, важных для определения сущностей. Вы знаете, что атрибут определенно «слишком важен для EAV», когда вы хотите использовать его в предложениях JOIN, ORDER BYs или WHERE. – grossvogel

ответ

1

Для ясности вы можете поместить элементы предложения join в предложение join, но с точки зрения оптимизации запросов, что в значительной степени способ сделать это.

Вы могли бы рассмотреть возможность переписать запрос на что-то вроде этого, хотя:

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" 
; 

Вы также можете нормализовать поле, чтобы сэкономить немного места (при условии, что поле не является перечисление)

+0

почему отдельные условия в 'ON' и' WHERE'? http://pastebin.com/FHY3HXuT – gondo

+0

Это, главным образом, соглашение, часть 'WHERE' на самом деле должна фильтровать результаты. «ON» - это условия фактического соединения, которые остались бы неизменными между запросами. – Wolph

+1

не было бы быстрее, если бы условия были оценены во время присоединения, а не после? – gondo

1

Хотя EAV имеет это место, у вас уже есть 3 несколько гарантированных имени атрибута (поскольку вы его ищите, я предполагаю, что многие объекты делят эти атрибуты). Пахнет как не-кандидат на EAV, или возможная комбинация атрибутов, которые могут идти в их отдельной таблице artistdates (id,artist,start,end), которые могли бы быть связаны в таблице EAV как E=<whatever>,A=artistdate_id,V=<artistdate_id>, если хотите.

Сила EAV для тех ситуаций, в которых фактические атрибуты присутствуют, непротиворечивы и которые обычно запрашиваются исключительно сущностью-идентификатором или наличием атрибута (возможно, в сочетании со значением). Как только вы ищете комбинации атрибутов, производительность будет страдать, и вопрос в том, должны ли они жить отдельно в структуре EAV или их следует разделить на «традиционную» таблицу на основе строк.

+1

Я знаю, что это можно сделать без EAV, к сожалению, я не имею права изменять базу данных. – blockhead

+1

Тогда, к сожалению, удар по производительности - это то, что вы должны предпринять. Ничего плохого в вашем фактическом запросе. – Wrikken

Смежные вопросы