sql >> Databáze >  >> RDS >> Mysql

Jak implementovat filtrační systém v SQL?

entity-attribute-value model, který navrhujete, by se do tohoto scénáře hodil.

Pokud jde o dotaz na filtrování, musíte pochopit, že s modelem EAV obětujete spoustu výkonu dotazů, takže to může být docela složité. Nicméně tento jeden způsob, jak vyřešit váš problém:

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;

Jednou neelegantní vlastností tohoto přístupu je, že musíte zadat počet párů atribut/hodnota, u kterých očekáváte shodu, v sub_t.matches = 2 . Pokud bychom měli tři podmínky, museli bychom zadat sub_t.matches = 3 , a tak dále.

Pojďme vytvořit testovací případ:

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

Dotaz:

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;

Výsledek:

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

Nyní vložíme další ovoce s color=yellow a taste=sweet :

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

Stejný dotaz by vrátil:

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

Pokud chceme tento výsledek omezit na entity s origin=MEXICO , museli bychom přidat další OR podmínku a zkontrolujte sub_t.matches = 3 místo 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;

Výsledek:

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

Jako každý přístup má i použití modelu EAV určité výhody a nevýhody. Ujistěte se, že téma důkladně prozkoumáte v kontextu vaší aplikace. Můžete dokonce zvážit alternativní relační databáze, jako je Cassandra , CouchDB , MongoDB , Voldemort , HBase , SimpleDB nebo jiné obchody s páry klíč–hodnota.



  1. Jak vrátit typ pole z dotazu MySQL?

  2. Jak na čísla pater v SQL

  3. Spojit tabulku v závislosti na hodnotě sloupce v hlavní tabulce

  4. kombinování dotazů mysql AND OR v Codeigniter