ООП и SQL-запрос для динамических атрибутов

У меня есть четыре класса: User, Attribute, Attribcategory, Attribvalue.

и четыре таблицы: tbl_user, tbl_attribute, tbl_attribcategory, tbl_attribvalue в базе данных.

это отношения между таблицами:

tbl_user 1 --- n tbl_attribvalue n --- 1 attribute 

(tbl_attribvalue — промежуточная таблица между атрибутом и пользователем

tbl_attribcategory 1 ---- n tbl_attribute

Это пример:

tbl_user
{id:1, name: Jack}



tbl_category {id:2,label: Career and Education}

tbl_attribute :
{id:1 ,category:2,label:employer , variable: employer}
{id:2 ,category:2,label: High school , variable: high_school}
{id:3 ,category:2,label:college , variable:college}

А поскольку tbl_attribvalue является промежуточной таблицей между tbl_attribute и tbl_user, мы должны знать идентификатор пользователя и идентификатор атрибута... чтобы знать значение атрибута пользователя.

пример

tbl_attribvalue {id:1,iduser:1,idattrib:3,value: Harvard University}

Эта система используется, когда у нас есть динамические атрибуты вместо статических меток в приложении.

Как насчет занятий?

Четыре класса: User, Attribute, Attribvalue, Attribcategory содержат геттеры, сеттеры и свойства каждый.

Я хочу вернуть все эти атрибуты, категории атрибутов и значения атрибутов для данного пользователя... Но я не знаю, какой именно метод использовать, это вопрос концепции.

У меня уже есть этот код в моем контроллере (в модели MVC):

$atcdata=array();
$attribcategory=new Attribcategory($atcdata);
$attribcategories=$manager->viewIt($attribcategory,' defined=0 AND ownertype=1');

$manager — это DBManager, он содержит функцию viewIt($object,$criteria), которая затем возвращает массив с результатами данного объекта, используя заданные критерии.

поэтому категории атрибутов будут содержать все категории.

Но как использовать эту информацию о категории для возврата атрибутов и значений атрибутов для данного пользователя?

Другими словами :

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

Этот пример данных будет отображаться следующим образом для данного пользователя

[attrcategory]
    [attribute] : [attrvalue]
                  [attrvalue]
                  [attrvalue]

Work & Education 
    Employer : Oracle 
               Microsoft

    College : Harvard
    High school : harvard

и тому подобное.

заранее спасибо


person SmootQ    schedule 10.06.2012    source источник


Ответы (1)


Вы делаете MVC неправильно.. но это не вопрос.

У вас там есть антишаблон 'Entry-Attribute-Value'. Он рассматривается в антипаттернах SQL (в одноименной главе). Вот что вызывает вашу проблему.

Чтобы получить все результаты в одном запросе, лучшее, что вы можете сделать, это стремиться к чему-то похожему на следующую структуру ответа:

[attrcategory] , [attribute] , [attrvalue]+[attrvalue]+[attrvalue]
[attrcategory] , [attribute] , [attrvalue]
[attrcategory] , [attribute] , [attrvalue]+[attrvalue]+[attrvalue]+[attrvalue]

Запрос, способный дать такой результат, будет выглядеть примерно так:

SELECT 
    AttributeCategories.title AS attrcategory, 
    Attributes.title AS attribute, 
    GROUP_CONCAT(DISTINCT AttribureValues.value
                 ORDER BY AttribureValues.value DESC SEPARATOR '+')
         AS list
FROM AttribureValues
    LEFT JOIN Attributes USING (attribute_id)
    LEFT JOIN AttributeCategories USING (category_id)
    LEFT JOIN Users USING (user_id)
WHERE 
    Users.name = 'John Smith'
GROUP BY Attributes.attribute_id

Затем в конце PHP вам нужно будет explode() значения в разделителе.

person tereško    schedule 10.06.2012
comment
и при отображении данных я думаю, что они будут отображаться следующим образом: Работодатель : Работодатель Oracle : Microsoft Должен ли я делать операторы if в представлениях для отображения только одного Работодателя атрибутов ?? - person SmootQ; 10.06.2012
comment
Нет, на самом деле, я имею в виду, что мне нужно сделать оператор if в представлении... и я не привык делать это :) - person SmootQ; 10.06.2012
comment
@SmootQ Я думаю, вы упускаете суть того, что GROUP_CONCAT() делает. Результат будет иметь имя значения и значение ALL (разделенные символом +). Для View не должно иметь значения, было ли значение одно или несколько, потому что все значения отображаются в одном и том же теге <ul>. - person tereško; 10.06.2012