sql >> Database >  >> RDS >> Mysql

Hoe een filtersysteem in SQL implementeren?

De entity-attribute-value model dat u voorstelt, zou in dit scenario kunnen passen.

Wat betreft de filterquery, je moet begrijpen dat je met het EAV-model veel zoekkracht opoffert, dus dit kan behoorlijk lastig worden. Maar dit is een manier om uw probleem aan te pakken:

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;

Een onelegant kenmerk van deze benadering is dat u het aantal attribuut/waarde-paren moet specificeren dat u verwacht te matchen in sub_t.matches = 2 . Als we drie voorwaarden hadden, hadden we sub_t.matches = 3 . moeten specificeren , enzovoort.

Laten we een testcase bouwen:

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

Vraag:

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;

Resultaat:

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

Laten we nu nog een vrucht invoegen met color=yellow en taste=sweet :

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

Dezelfde zoekopdracht zou terugkeren:

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

Als we dit resultaat willen beperken tot entiteiten met origin=MEXICO , zouden we nog een OR . moeten toevoegen staat en controleer op sub_t.matches = 3 in plaats van 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;

Resultaat:

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

Zoals bij elke benadering zijn er bepaalde voor- en nadelen bij het gebruik van het EAV-model. Zorg ervoor dat u het onderwerp uitgebreid onderzoekt in de context van uw aanvraag. U kunt zelfs een alternatieve relationele database overwegen, zoals Cassandra , CouchDB , MongoDB , Voldemort , HBase , SimpleDB of andere sleutelwaardewinkels.



  1. NOLOCK Hint gebruiken in EF4?

  2. MySQL PHP-groep per dag en totaal voor elke dag

  3. mysql selecteer om spaties terug te geven voor alles behalve de eerste rij van herhalende kolommen

  4. sql groeperen op versus onderscheiden