Ce ne doit pas être considérée comme une réponse exhaustive, mais seulement quelques points sur le sujet.
Puisque la question est étiquetée avec la balise [mysql]
, laissez-moi vous dire que, en général, relational databases ne sont pas particulièrement adaptés pour stocker des données en utilisant le modèle EAV. Vous pouvez toujours concevoir un modèle EAV en SQL, mais vous devrez sacrifier de nombreux avantages qu'une base de données relationnelle vous donnerait. Non seulement vous ne serez pas en mesure d'appliquer l'intégrité référentielle, d'utiliser des types de données SQL pour les valeurs et d'appliquer des attributs obligatoires, mais même les requêtes très basiques (comme celle-ci) peuvent devenir difficiles à écrire. En fait, pour surmonter cette limitation, plusieurs solutions EAV s'appuient sur la duplication de données, au lieu de se joindre à des tables connexes, ce qui, comme vous pouvez l'imaginer, présente de nombreux inconvénients.
Si vous avez vraiment besoin d'une conception sans schéma, vous pouvez envisager d'utiliser une solution NoSQL. Même si les faiblesses d'EAV par rapport aux bases de données relationnelles s'appliquent également aux alternatives NoSQL, des fonctionnalités supplémentaires difficiles à obtenir avec les bases de données SQL conventionnelles vous seront proposées. Par exemple, les datastores NoSQL peuvent généralement être mis à l'échelle beaucoup plus facilement que les bases de données relationnelles, simplement parce qu'ils ont été conçus pour résoudre un problème d'évolutivité, et ils ont volontairement supprimé les fonctions qui rendent la mise à l'échelle difficile.
D'autre part, @Ronnis' solution devrait fonctionner, et en général, en utilisant COUNT()
est une technique courante pour résoudre votre problème.
cas de test:
CREATE TABLE `cars` (carId int, carName char(1));
CREATE TABLE `car_names` (nameId int, carName char(1));
CREATE TABLE `car_attributes` (nameId int, attribute varchar(40));
INSERT INTO `cars` VALUES (1, 'a');
INSERT INTO `cars` VALUES (2, 'a');
INSERT INTO `cars` VALUES (3, 'b');
INSERT INTO `cars` VALUES (4, 'b');
INSERT INTO `cars` VALUES (5, 'b');
INSERT INTO `cars` VALUES (6, 'c');
INSERT INTO `cars` VALUES (7, 'd');
INSERT INTO `cars` VALUES (8, 'e');
INSERT INTO `cars` VALUES (9, 'f');
INSERT INTO `cars` VALUES (10, 'g');
INSERT INTO `car_names` VALUES (1, 'a');
INSERT INTO `car_names` VALUES (2, 'b');
INSERT INTO `car_names` VALUES (3, 'c');
INSERT INTO `car_names` VALUES (4, 'd');
INSERT INTO `car_names` VALUES (5, 'e');
INSERT INTO `car_names` VALUES (6, 'f');
INSERT INTO `car_names` VALUES (7, 'g');
INSERT INTO `car_attributes` VALUES (1, 'FAST');
INSERT INTO `car_attributes` VALUES (1, 'SMALL');
INSERT INTO `car_attributes` VALUES (1, 'SHINY');
INSERT INTO `car_attributes` VALUES (2, 'BIG');
INSERT INTO `car_attributes` VALUES (2, 'SLOW');
INSERT INTO `car_attributes` VALUES (3, 'EXPENSIVE');
INSERT INTO `car_attributes` VALUES (4, 'SHINY');
INSERT INTO `car_attributes` VALUES (5, 'FAST');
INSERT INTO `car_attributes` VALUES (5, 'SMALL');
INSERT INTO `car_attributes` VALUES (6, 'FAST');
INSERT INTO `car_attributes` VALUES (7, 'SMALL');
Résultat:
SELECT a.carId
FROM cars a
JOIN car_names b USING(carName)
JOIN car_attributes c USING(nameId)
WHERE c.attribute IN('SMALL', 'FAST')
GROUP BY a.carId
HAVING COUNT(distinct c.attribute) = 2;
+-------+
| carId |
+-------+
| 1 |
| 2 |
| 8 |
+-------+
3 rows in set (0.00 sec)
+1 ... Bonne réponse. Testé et fonctionne :) –
Fonctionne très bien mais je ne comprends pas l'importance du groupe en ayant compte une réponse rapide? – Tristan
Le groupe en partitionne les lignes en groupes de carId. Dans chaque groupe, il y aura plusieurs lignes.La clause having implémente votre condition AND car il y aura exactement 2 valeurs différentes pour l'attribut. – Ronnis