2010-12-04 4 views
2

J'ai trois tables un peu comme dans l'exemple ci-dessous:bases Sélectionnez entrées sur plusieurs entrées dans une autre table MySQL

TABLEAU CARS

carId carName 
----- -------- 
1  a 
2  a 
3  b 
4  b 
5  b 
6  c 
7  d 
8  e 
9  f 
10  g 

TABLEAU CAR NAMES

nameId carName 
------ ------- 
1  a 
2  b 
3  c 
4  d 
5  e 
6  f 
7  g 

TABLEAU CAR ATTRIBUTES

nameId attribute 
------ --------- 
1  FAST 
1  SMALL 
1  SHINY 
2  BIG 
2  SLOW 
3  EXPENSIVE 
4  SHINY 
5  FAST 
5  SMALL 
6  FAST 
7  SMALL 

J'ai essayé de mettre en place une requête pour obtenir le carid où il a des attributs à la fois rapide et léger, mais ai eu aucune chance. Quelle est la meilleure façon de procéder?

Dans cet exemple, le résultat serait carid 1 et RARnom un attribut où = SMALL et attribut = FAST

Répondre

3

Vous cherchez quelque chose comme ça? (non testé)

select a.carId 
    from cars  a 
    join car_names b using(carName) 
    join car_attribs c using(nameId) 
where c.attribute in('SMALL', 'FAST') 
group 
    by a.carId 
having count(distinct c.attribute) = 2; 
+0

+1 ... Bonne réponse. Testé et fonctionne :) –

+0

Fonctionne très bien mais je ne comprends pas l'importance du groupe en ayant compte une réponse rapide? – Tristan

+0

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

2

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) 
Questions connexes