Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment implémenter le système de filtrage en SQL ?

La entity-attribute-value modèle que vous suggérez pourrait s'adapter à ce scénario.

En ce qui concerne la requête de filtrage, vous devez comprendre qu'avec le modèle EAV, vous sacrifierez beaucoup de puissance de requête, cela peut donc devenir assez délicat. Cependant, voici une façon de résoudre votre problème :

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;

Une caractéristique peu élégante de cette approche est que vous devez spécifier le nombre de paires attribut/valeur que vous vous attendez à faire correspondre dans sub_t.matches = 2 . Si nous avions eu trois conditions, nous aurions dû spécifier sub_t.matches = 3 , et ainsi de suite.

Créons un scénario de test :

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');

Requête :

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;

Résultat :

+-------+
| id    |
+-------+
| mango |
+-------+
1 row in set (0.02 sec)

Insérons maintenant un autre fruit avec color=yellow et taste=sweet :

INSERT INTO stuff VALUES ('pear', 'color', 'yellow');
INSERT INTO stuff VALUES ('pear', 'taste', 'sweet');
INSERT INTO stuff VALUES ('pear', 'origin', 'somewhere');

La même requête renverrait :

+-------+
| id    |
+-------+
| mango |
| pear  |
+-------+
2 rows in set (0.00 sec)

Si nous voulons restreindre ce résultat aux entités avec origin=MEXICO , il faudrait ajouter un autre OR condition et vérifiez sub_t.matches = 3 au lieu de 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;

Résultat :

+-------+
| id    |
+-------+
| mango |
+-------+
1 row in set (0.00 sec)

Comme dans toute approche, l'utilisation du modèle EAV présente certains avantages et inconvénients. Assurez-vous de faire des recherches approfondies sur le sujet dans le contexte de votre candidature. Vous pouvez même envisager des bases de données relationnelles alternatives, telles que Cassandra , CouchDB , MongoDB , Voldemort , HBase , SimpleDB ou d'autres magasins de valeurs-clés.