entity-attribute-value modell som du föreslår skulle kunna passa i detta scenario.
När det gäller filtreringsfrågan måste du förstå att med EAV-modellen kommer du att offra massor av frågekraft, så detta kan bli ganska knepigt. Men det här ett sätt att lösa ditt problem:
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;
En inelegant egenskap hos detta tillvägagångssätt är att du måste ange antalet attribut/värdepar som du förväntar dig att matcha i sub_t.matches = 2
. Om vi hade tre villkor skulle vi ha behövt ange sub_t.matches = 3
, och så vidare.
Låt oss bygga ett testfall:
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');
Fråga:
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;
Resultat:
+-------+
| id |
+-------+
| mango |
+-------+
1 row in set (0.02 sec)
Låt oss nu infoga en annan frukt med color=yellow
och taste=sweet
:
INSERT INTO stuff VALUES ('pear', 'color', 'yellow');
INSERT INTO stuff VALUES ('pear', 'taste', 'sweet');
INSERT INTO stuff VALUES ('pear', 'origin', 'somewhere');
Samma fråga skulle returnera:
+-------+
| id |
+-------+
| mango |
| pear |
+-------+
2 rows in set (0.00 sec)
Om vi vill begränsa detta resultat till enheter med origin=MEXICO
, skulle vi behöva lägga till en annan OR
condition och kontrollera efter sub_t.matches = 3
istället för 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;
Resultat:
+-------+
| id |
+-------+
| mango |
+-------+
1 row in set (0.00 sec)
Som i alla tillvägagångssätt finns det vissa fördelar och nackdelar när man använder EAV-modellen. Se till att du undersöker ämnet noggrant i samband med din ansökan. Du kanske till och med vill överväga en alternativ relationsdatabaser, som Cassandra , CouchDB , MongoDB , Voldemort , HBase , SimpleDB eller andra nyckel-värde butiker.