Der entity-attribute-value Modell, das Sie vorschlagen, könnte in dieses Szenario passen.
In Bezug auf die Filterabfrage müssen Sie verstehen, dass Sie mit dem EAV-Modell viel Abfrageleistung opfern, sodass dies ziemlich schwierig werden kann. Aber diese eine Möglichkeit, Ihr Problem anzugehen:
SELECT stuff.id
FROM stuff
JOIN (SELECT COUNT(*) matches
FROM table
WHERE (`key` = X1 AND `value` = V1) OR
(`key` = X2 AND `value` = V2)
GROUP BY id
) sub_t ON (sub_t.matches = 2 AND sub_t.id = stuff.id)
GROUP BY stuff.id;
Ein unelegantes Merkmal dieses Ansatzes besteht darin, dass Sie die Anzahl der Attribut/Wert-Paare angeben müssen, die Sie in sub_t.matches = 2
erwarten . Wenn wir drei Bedingungen hätten, hätten wir sub_t.matches = 3
angeben müssen , und so weiter.
Lassen Sie uns einen Testfall erstellen:
CREATE TABLE stuff (`id` varchar(20), `key` varchar(20), `value` varchar(20));
INSERT INTO stuff VALUES ('apple', 'color', 'red');
INSERT INTO stuff VALUES ('mango', 'color', 'yellow');
INSERT INTO stuff VALUES ('banana', 'color', 'yellow');
INSERT INTO stuff VALUES ('apple', 'taste', 'sweet');
INSERT INTO stuff VALUES ('mango', 'taste', 'sweet');
INSERT INTO stuff VALUES ('banana', 'taste', 'bitter-sweet');
INSERT INTO stuff VALUES ('apple', 'origin', 'US');
INSERT INTO stuff VALUES ('mango', 'origin', 'MEXICO');
INSERT INTO stuff VALUES ('banana', 'origin', 'US');
Abfrage:
SELECT stuff.id
FROM stuff
JOIN (SELECT COUNT(*) matches, id
FROM stuff
WHERE (`key` = 'color' AND `value` = 'yellow') OR
(`key` = 'taste' AND `value` = 'sweet')
GROUP BY id
) sub_t ON (sub_t.matches = 2 AND sub_t.id = stuff.id)
GROUP BY stuff.id;
Ergebnis:
+-------+
| id |
+-------+
| mango |
+-------+
1 row in set (0.02 sec)
Jetzt fügen wir eine weitere Frucht mit color=yellow
ein und taste=sweet
:
INSERT INTO stuff VALUES ('pear', 'color', 'yellow');
INSERT INTO stuff VALUES ('pear', 'taste', 'sweet');
INSERT INTO stuff VALUES ('pear', 'origin', 'somewhere');
Die gleiche Abfrage würde zurückgeben:
+-------+
| id |
+-------+
| mango |
| pear |
+-------+
2 rows in set (0.00 sec)
Wenn wir dieses Ergebnis auf Entitäten mit origin=MEXICO
beschränken möchten , müssten wir ein weiteres OR
hinzufügen Bedingung und prüfen Sie auf sub_t.matches = 3
statt 2
.
SELECT stuff.id
FROM stuff
JOIN (SELECT COUNT(*) matches, id
FROM stuff
WHERE (`key` = 'color' AND `value` = 'yellow') OR
(`key` = 'taste' AND `value` = 'sweet') OR
(`key` = 'origin' AND `value` = 'MEXICO')
GROUP BY id
) sub_t ON (sub_t.matches = 3 AND sub_t.id = stuff.id)
GROUP BY stuff.id;
Ergebnis:
+-------+
| id |
+-------+
| mango |
+-------+
1 row in set (0.00 sec)
Wie bei jedem Ansatz gibt es auch bei der Verwendung des EAV-Modells gewisse Vor- und Nachteile. Stellen Sie sicher, dass Sie das Thema im Kontext Ihrer Bewerbung ausführlich recherchieren. Vielleicht möchten Sie sogar alternative relationale Datenbanken wie Cassandra in Betracht ziehen , CouchDB , MongoDB , Voldemort , HBase , SimpleDB oder andere Schlüsselwertspeicher.