我有一个数据库结构,旨在以易于扩展的方式存储特定对象的属性。
有一个“对象”表。
+----+----------------------
| id | ....(name, type, etc)
+----+----------------------
接下来,我有一个“属性”表。
+----+------+
| id | Name |
+----+------+
最后,“关系”表,用于将所有数据保存为具有相应值的属性-对象对(作为主键)。
+--------+---------+-------+
| id_obj | id_attr | value |
+--------+---------+-------+
我需要一次获取满足多个条件的对象的 ID。例如,我有名为“Type”和“City”的属性,我需要获取这些属性的对应值为“Apartment”和“City b”的对象的 ID。
自昨天以来,我在用头撞墙后设法想出了最好的解决方案(嗯,这个查询的唯一好处是它实际上有效并获取了所需的记录):
SELECT objects.id
FROM (attributes INNER JOIN relations ON attributes.id = relations.id_attr)
INNER JOIN objects ON relations.id_obj = objects.id
WHERE objects.id
IN (
SELECT objects.id
FROM (attributes INNER JOIN relations ON attributes.id = relations.id_attr)
INNER JOIN objects ON relations.id_obj = objects.id
WHERE attributes.name = 'Type' AND relations.value = 'Apartment'
)
AND objects.id
IN (
SELECT objects.id
FROM (attributes INNER JOIN relations ON attributes.id = relations.id_attr)
INNER JOIN objects ON relations.id_obj = objects.id
WHERE attributes.name = 'City' AND relations.value = 'City b'
)
GROUP BY objects.id ASC
LIMIT 0 , 20
问题是,存储的数据量可能会变得有点大,而且我担心所有这些子查询(可能需要指定一些 10-15 个过滤器),每个子查询都解析整个数据库,可能会导致严重的性能问题(并不是说即使我的 SQL 技能有限,我也很确定一定有更好的方法来完成我需要做的事情)。
另一方面,对数据库进行大幅更改并不是真正的选择,因为使用它的代码在很大程度上取决于当前的数据库结构。
有没有一种方法可以在单个查询中按照我需要的方式检查属性,并且对存储的数据结构进行有限的更改或不进行更改?
工作查询相当于上面的查询,但优化得更好,归功于DRapp https://stackoverflow.com/users/74195/drapp :
SELECT STRAIGHT_JOIN
rel.id_obj
from
relations rel
join attributes atr
on rel.id_attr = atr.id
where
( rel.value = 'Apartment' AND atr.name = 'Type' )
or ( rel.value = 'City b' AND atr.name = 'City' )
group by
rel.id_obj
having
count(*) = 2
limit
0, 20