问题
I have 3 tables like this.
Entity_Table
|e_id|e_name|e_type |e_tenant|
|1 | Bob | bird | owner_1|
|2 | Joe | cat | owner_1|
|3 | Joe | cat | owner_2|
AttributeValue_Table
|av_id|prop_name |prop_value|
|1 | color | black |
|2 | color | white |
|3 | wing size| 7" |
|4 | whiskers | long |
|5 | whiskers | short |
|6 | random | anything |
Entity_AttrVal
|e_id|av_id|
| 1 | 1 |
| 1 | 3 |
| 2 | 2 |
| 2 | 5 |
| 3 | 1 |
| 3 | 4 |
| 3 | 6 |
What I want to be able to do is something like 'find entity where e_name='Joe' and color=black and whiskers=short.
I can obtain a result set where each row has 1 prop/value, along with the entity information, so querying on one property works. But I need to be able to do arbitrary N properties. How do I do something like this?
Can I build a join table with all properties as columns or something
edit2: Looks like I can do something like this
SELECT et.e_id, et.e_name, et.e_type
FROM Entitiy_table et
LEFT JOIN Entity_AttrVal j ON et.e_id = j.e_id
RIGHT JOIN AttributeValue_Table at ON at.av_id = j.av_id
WHERE (av.prop_name='color' AND av.prop_value='white') OR (av.prop_name='whiskers' AND av.prop_value='long')
GROUP BY et.e_id, et.e_name, et.e_type
HAVING COUNT(*) = 2;
回答1:
You have to add a predicate for each name/value combination:
SELECT <whatever you need>
FROM Entity_Table et
WHERE et.e_name = 'Joe'
AND EXISTS (SELECT 1
FROM AttributeValue_Table avt
JOIN Entity_AttrVal ea ON ea.e_id = et.e_id
WHERE ea.a_id = avt.av_id
AND avt.prop_name = 'color'
AND avt.prop_value = 'black')
AND EXISTS (SELECT 1
FROM AttributeValue_Table avt
JOIN Entity_AttrVal ea ON ea.e_id = et.e_id
WHERE ea.a_id = avt.av_id
AND avt.prop_name = 'whiskers'
AND avt.prop_value = 'short')
(I apologize if my Sql Server dialect shines through)
To do an arbitrary number of comparisons, you'd have to generate the SQL and execute it.
As said in a comment, this goes to show that EAV is a pain (an anti-pattern, really), but I know by experience that sometimes there's simply no alternative if we're bound to a relational database.
来源:https://stackoverflow.com/questions/36432744/querying-on-eav-sql-design