sql >> Databasteknik >  >> RDS >> Mysql

Hur implementerar man filtersystem i SQL?

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.



  1. Implementera MariaDB-replikering för hög tillgänglighet

  2. Varför använder MySQL inte ett index för en större än jämförelse?

  3. Hur man genererar tabell API-paket i Oracle SQL Developer?

  4. Hur får man distinkt post från mysql-tabellen?