开发者

Select entries bases on multiple entries in another table MySQL

I have three tables kinda like the example below:

TABLE CARS

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

TABLE CAR NAMES

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

TABLE CAR ATTRIBUTES

nameId  attribute
------  ---------
1       FAST
1       SMALL
1       SHI开发者_如何学运维NY
2       BIG
2       SLOW
3       EXPENSIVE
4       SHINY
5       FAST
5       SMALL
6       FAST
7       SMALL

I have been trying to put together a query to get the carId where it has attributes of both FAST and SMALL, but have been having no luck. What is the best way to do this?

In this example the result would be carID 1 and carName a where attribute = SMALL and attribute = FAST


Looking for something like this? (untested)

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;


This is not to be considered an exhaustive answer, but just a few points on the topic.

Since the question is tagged with the [mysql] tag, let me say that, in general, relational databases aren't particularly suitable for storing data using the EAV model. You can still design an EAV model in SQL, but you will have to sacrifice many advantages that a relational database would give. Not only you won't be able to enforce referential integrity, use SQL data types for values and enforce mandatory attributes, but even the very basic queries (like this one) can become difficult to write. In fact, to overcome this limitation, several EAV solutions rely on data duplication, instead of joining with related tables, which as you can imagine, has plenty of drawbacks.

If you really require a schemaless design, you could consider using a NoSQL solution. Even though the weaknesses of EAV relative to relational databases also apply to NoSQL alternatives, you will be offered additional features that are difficult to achieve with conventional SQL databases. For example, usually NoSQL datastores can be scaled much easier than relational databases, simply because they were designed to solve some sort of scalability problem, and they intentionally dropped features that make scaling difficult.

On the other hand, @Ronnis' solution should work, and in general, using COUNT() is one common technique to solve your problem.

Test case:

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

Result:

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)
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜