SmootQ
SmootQ

Reputation: 2122

OOP and SQL Query for dynamic attributes

I have four classes : User, Attribute, Attribcategory, Attribvalue.

and four tables : tbl_user, tbl_attribute, tbl_attribcategory, tbl_attribvalue in the database.

those are the relations between tables :

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

(tbl_attribvalue is intermediate table between attribute and user

tbl_attribcategory 1 ---- n tbl_attribute

This is an example :

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}

And as the tbl_attribvalue is an intermediate table between tbl_attribute and tbl_user, we should know the user id , and the attribute id...to know the value of the attribute of the user .

Exemple

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

This system is used when we have dynamic attributes instead of static labels in the application.

What about classes?

The four classes : User, Attribute, Attribvalue , Attribcategory contain getters and setters and properties each.

I want to return all those attributes, attribcategories and attribvalues for a given user... But I don't know what method to use exactly, it's a matter conception.

I have already this code in my controller (In MVC Model) :

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

$manager is a DBManager, it contains a function viewIt($object,$criteria), which then returns an array with the results of the given object, using the given criteria.

so attrib categories is gonna contain all the categories.

But How to use those category information to return the attributes and attribvalues for the given user?

In other words :

I know how to return them , but In terms of performance, I don't want to use more than two queries to get all the data.

This data example will be displayed as follows for a given user

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

Work & Education 
    Employer : Oracle 
               Microsoft

    College : Harvard
    High school : harvard

and the like.

Thank you in advance

Upvotes: 1

Views: 605

Answers (1)

tereško
tereško

Reputation: 58444

You are doing MVC wrong .. but that's not the question.

What you have there, is a 'Entry-Attribute-Value' antipattern. It is explored in SQL Antipatterns (in chapter with same title). That is what's causing your problem.

To get all the results in single query, the best you can do is to aim for something resembling following response structure:

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

The query able to produce such result would look approximately like this:

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

Then on PHP end of things you will have to explode() values on separator.

Upvotes: 1

Related Questions