Ich habe eine DB-Struktur, die entworfen ist, um Attribute für bestimmte Objekte in einer leicht erweiterbaren Weise zu speichern.
Es gibt eine Tabelle "Objekte".
+----+----------------------
| id | ....(name, type, etc)
+----+----------------------
Als nächstes habe ich eine Tabelle "Attribute".
+----+------+
| id | Name |
+----+------+
Und schließlich eine Tabelle "Beziehungen", in der alle Daten als Attribut-Objekt-Paare (als Primärschlüssel) mit den entsprechenden Werten gespeichert werden.
+--------+---------+-------+
| id_obj | id_attr | value |
+--------+---------+-------+
Ich muss IDs für Objekte abrufen, die mehrere Bedingungen auf einmal erfüllen. Ich habe z. B. Attribute mit den Namen "Typ" und "Stadt", und ich muss IDs für die Objekte abrufen, bei denen die entsprechenden Werte für diese Attribute "Wohnung" und "Stadt b" sind.
Die beste Lösung, die mir eingefallen ist, nachdem ich seit gestern mit dem Kopf gegen die Wand geschlagen habe (das einzig Gute an dieser Abfrage ist, dass sie tatsächlich funktioniert und die benötigten Datensätze abruft):
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
Die Sache ist, die Menge der gespeicherten Daten kann möglicherweise etwas groß werden, und ich fürchte, dass alle diese Unterabfragen (es könnte Notwendigkeit, einige 10-15 Filter angeben), jede die ganze DB analysiert, ernsthafte Leistungsprobleme verursachen kann (nicht zu sagen, dass sogar mit meiner begrenzten SQL-Kenntnisse ich ziemlich sicher, dass es einen besseren Weg zu tun, was ich tun müssen).
Andererseits sind drastische Änderungen an der DB nicht wirklich eine Option, da der Code, der damit arbeitet, stark von der aktuellen DB-Struktur abhängt.
Gibt es eine Möglichkeit, die Attribute so zu überprüfen, wie ich es in einer einzigen Abfrage benötige, mit einer begrenzten Menge oder ohne Änderungen an der gespeicherten Datenstruktur?
Die Arbeitsabfrage, die der obigen Abfrage entspricht, aber viel besser optimiert ist, lautet 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