2010-03-15 5 views
4

J'ai 3 tables que j'essaie de rejoindre et j'obtiens des résultats distincts.MySQL Multiple Table Join

CREATE TABLE `car` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL DEFAULT '', 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB 

mysql> select * from car; 

+----+-------+ 
| id | name | 
+----+-------+ 
| 1 | acura | 
+----+-------+ 




CREATE TABLE `tires` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `tire_desc` varchar(255) DEFAULT NULL, 
    `car_id` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `new_fk_constraint` (`car_id`), 
    CONSTRAINT `new_fk_constraint` FOREIGN KEY (`car_id`) REFERENCES `car` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB 

mysql> select * from tires; 

+----+-------------+--------+ 
| id | tire_desc | car_id | 
+----+-------------+--------+ 
| 1 | front_right |  1 | 
| 2 | front_left |  1 | 
+----+-------------+--------+ 


CREATE TABLE `lights` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `lights_desc` varchar(255) NOT NULL, 
    `car_id` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `new1_fk_constraint` (`car_id`), 
    CONSTRAINT `new1_fk_constraint` FOREIGN KEY (`car_id`) REFERENCES `car` (`id`) ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB 

mysql> select * from lights; 

+----+-------------+--------+ 
| id | lights_desc | car_id | 
+----+-------------+--------+ 
| 1 | right_light |  1 | 
| 2 | left_light |  1 | 
+----+-------------+--------+ 

Voici ma requête.

mysql> SELECT name, group_concat(tire_desc), group_concat(lights_desc) 
FROM car 
left join tires on car.id = tires.car_id 
left join lights on car.id = car_id 
group by car.id; 

+-------+-----------------------------------------------+-----------------------------------------------+ 
| name | group_concat(tire_desc)      | group_concat(lights_desc)      | 
+-------+-----------------------------------------------+-----------------------------------------------+ 
| acura | front_right,front_right,front_left,front_left | right_light,left_light,right_light,left_light | 
+-------+-----------------------------------------------+-----------------------------------------------+ 

Je reçois des doublons et c'est ce que je voudrais obtenir.

+-------+-----------------------------------------------+--------------------------------+ 
| name | group_concat(tire_desc) | group_concat(lights_desc) | 
+-------+-----------------------------------------------+--------------------------------+ 
| acura | front_right,front_left | right_light,left_light | 
+-------+-----------------------------------------------+--------------------------------+ 

Je ne peux pas utiliser distinctes dans group_concat parce que je pourrais avoir des doublons légitimes que je voudrais garder. Est-il possible de faire cette requête en utilisant des jointures et en n'utilisant pas les sélections internes comme l'énoncé ci-dessous?

SELECT name, 
(select group_concat(tire_desc) from tires where car.id = tires.car_id), 
(select group_concat(lights_desc) from lights where car.id = lights.car_id) 
FROM car 

De plus, si j'utilise des sélections internes, y aura-t-il des problèmes de performance par rapport aux jointures?

Répondre

0

Existe-t-il un moyen d'effectuer cette requête à l'aide de jointures et de ne pas utiliser de sélection interne comme l'instruction ci-dessous?

Il y a, mais pas aussi efficace et peut omettre des doublons destinés:

SELECT name, group_concat(DISTINCT tire_desc), group_concat(DISTINCT lights_desc) 
FROM car 
left join tires on car.id = tires.car_id 
left join lights on car.id = car_id 
group by car.id; 

De plus, si je vais utiliser sélectionne intérieur, qu'il y aura des problèmes de performance sur jointures?

Dans votre cas, oui: les sous-sélections seront plus rapides.

Sur MyISAM tables, dans certains cas, les sous-requêtes ont tendance à être plus rapide que GROUP BY requêtes, en raison du fait que GROUP BY dans MyISAM est assez cher en raison de tri/matérialisation des frais généraux:

0

Peut-être que vous devez spécifier quel car_id vous voulez dire dans la seconde ON

SELECT name, group_concat(tire_desc), group_concat(lights_desc) 
FROM car 
left join tires on car.id = tires.car_id 
left join lights on car.id = **lights**.car_id 
group by car.id; 

Je crois que les jointures sont plus rapides que les sous-requêtes sur les tables InnoDB.