Mysql
 sql >> Baza danych >  >> RDS >> Mysql

Jak zaimplementować system filtrów w SQL?

wartość-atrybutu-encji model, który sugerujesz, może pasować do tego scenariusza.

Jeśli chodzi o zapytanie filtrujące, musisz zrozumieć, że w przypadku modelu EAV poświęcisz dużo mocy zapytań, więc może to stać się dość trudne. Jednak ten jeden sposób na rozwiązanie problemu:

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;

Jedną nieelegancką cechą tego podejścia jest to, że musisz określić liczbę par atrybut/wartość, które mają być dopasowane w sub_t.matches = 2 . Gdybyśmy mieli trzy warunki, musielibyśmy określić sub_t.matches = 3 i tak dalej.

Zbudujmy przypadek testowy:

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

Zapytanie:

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;

Wynik:

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

Teraz wstawmy kolejny owoc z color=yellow i taste=sweet :

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

To samo zapytanie zwróci:

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

Jeśli chcemy ograniczyć ten wynik do podmiotów z origin=MEXICO , musielibyśmy dodać kolejny OR warunek i sprawdź, czy sub_t.matches = 3 zamiast 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;

Wynik:

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

Jak w każdym podejściu, korzystanie z modelu EAV ma swoje zalety i wady. Upewnij się, że dokładnie zbadałeś temat w kontekście swojej aplikacji. Możesz nawet rozważyć alternatywne relacyjne bazy danych, takie jak Cassandra , CouchDB , MongoDB , Voldemort , HBase , SimpleDB lub inne sklepy klucz-wartość.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. PHP Sprawdź, czy ciąg zawiera literę

  2. Numer linii sklepu MySQL LOAD DATA INFILE

  3. MySQL Niewrażliwy na wielkość liter, ale wrażliwy na akcenty UTF8 Unikalny klucz

  4. Jak aliasować pole lub kolumnę w MySQL?

  5. Sphinx bez użycia identyfikatora auto_increment