sql >> Base de Datos >  >> RDS >> Mysql

¿Cómo implementar el sistema de filtro en SQL?

El entity-attribute-value modelo que usted sugiere podría encajar en este escenario.

Con respecto a la consulta de filtrado, debe comprender que con el modelo EAV sacrificará mucho poder de consulta, por lo que esto puede volverse bastante complicado. Sin embargo, esta es una forma de abordar su problema:

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;

Una característica poco elegante de este enfoque es que debe especificar la cantidad de pares de atributo/valor que espera que coincidan en sub_t.matches = 2 . Si tuviéramos tres condiciones, tendríamos que especificar sub_t.matches = 3 , y así sucesivamente.

Construyamos un caso de prueba:

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

Consulta:

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;

Resultado:

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

Ahora insertemos otra fruta con color=yellow y taste=sweet :

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

La misma consulta devolvería:

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

Si queremos restringir este resultado a entidades con origin=MEXICO , tendríamos que agregar otro OR condición y verifique sub_t.matches = 3 en lugar 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;

Resultado:

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

Como en todo enfoque, existen ciertas ventajas y desventajas cuando se utiliza el modelo EAV. Asegúrese de investigar el tema extensamente en el contexto de su aplicación. Incluso puede considerar una base de datos relacional alternativa, como Cassandra , CouchDB , MongoDB , Voldemort , HBase , SimpleDB u otras tiendas clave-valor.