Querying on EAV SQL Design

空扰寡人 提交于 2019-12-12 04:06:57

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!