2016-09-22 2 views
0

ПОДГОТОВКАВыберите строки, которые косвенно ссылаются в другой таблице

Рассмотрим этот скрипт для создания MySQL фиктивный базы данных:

CREATE SCHEMA `zzz_dummy` ; 
CREATE TABLE `zzz_dummy`.`subtable2` (
    `id` INT NOT NULL UNIQUE, 
    `col1` VARCHAR(45) NULL, 
    PRIMARY KEY (`id`)); 
CREATE TABLE `zzz_dummy`.`subtable1` (
    `id` INT NOT NULL UNIQUE, 
    `ref_subtab2` INT NULL, 
    PRIMARY KEY (`id`)); 
CREATE TABLE `zzz_dummy`.`maintable` (
    `id` INT NOT NULL UNIQUE, 
    `ref_subtab1` INT NULL, 
    PRIMARY KEY (`id`)); 

ALTER TABLE `zzz_dummy`.`maintable` 
ADD INDEX `fk_subtab1_idx` (`ref_subtab1` ASC); 
ALTER TABLE `zzz_dummy`.`maintable` 
ADD CONSTRAINT `fk_subtab1` 
    FOREIGN KEY (`ref_subtab1`) 
    REFERENCES `zzz_dummy`.`subtable1` (`id`) 
    ON DELETE NO ACTION 
    ON UPDATE NO ACTION; 


ALTER TABLE `zzz_dummy`.`subtable1` 
ADD INDEX `fk_subtab2_idx` (`ref_subtab2` ASC); 
ALTER TABLE `zzz_dummy`.`subtable1` 
ADD CONSTRAINT `fk_subtab2` 
    FOREIGN KEY (`ref_subtab2`) 
    REFERENCES `zzz_dummy`.`subtable2` (`id`) 
    ON DELETE NO ACTION 
    ON UPDATE NO ACTION; 

INSERT INTO zzz_dummy.subtable2 VALUES 
    (1,'ref_val_1'), 
    (2,'ref_val_2'), 
    (3,'no_ref'); 

INSERT INTO zzz_dummy.subtable1 VALUES 
    (1,'1'), 
    (2,'2'), 
    (3,'3'); 

INSERT INTO zzz_dummy.maintable VALUES 
    (1,'1'), 
    (2,'2'), 
    (3,'1'), 
    (4,'1'), 
    (5,'2'), 
    (6,'1'); 

Это будет производить следующие таблицы и записи:

maintable: 
+----+-------------+ 
| id | ref_subtab1 | 
+----+-------------+ 
| 1 |   1 | 
| 3 |   1 | 
| 4 |   1 | 
| 6 |   1 | 
| 2 |   2 | 
| 5 |   2 | 
+----+-------------+ 

subtable1: 
+----+-------------+ 
| id | ref_subtab2 | 
+----+-------------+ 
| 1 |   1 | 
| 2 |   2 | 
| 3 |   3 | 
+----+-------------+ 

subtable2: 
+----+-----------+ 
| id | col1  | 
+----+-----------+ 
| 1 | ref_val_1 | 
| 2 | ref_val_2 | 
| 3 | no_ref | 
+----+-----------+ 

ПРОБЛЕМА

Как вы можете видеть, столбец ref_subtab1 в maintable ссылок id в subtable1, что колонка ref_subtab2 наконец ссылается на subtable2id. Я хочу выбрать все строки в subtable2, косвенно упомянутые выше.

Я попытался

SELECT subtable2.* FROM zzz_dummy.subtable2 
    INNER JOIN zzz_dummy.maintable 
    INNER JOIN zzz_dummy.subtable1 
    WHERE zzz_dummy.maintable.ref_subtab1=zzz_dummy.subtable1.id 
    AND zzz_dummy.subtable1.ref_subtab2=zzz_dummy.subtable2.id; 

но это возвращает 6 результатов, один для каждого матча в maintable:

+----+-----------+ 
| id | col1  | 
+----+-----------+ 
| 1 | ref_val_1 | 
| 1 | ref_val_1 | 
| 1 | ref_val_1 | 
| 1 | ref_val_1 | 
| 2 | ref_val_2 | 
| 2 | ref_val_2 | 
+----+-----------+ 

Я не хочу избыточных значений, я хотел бы его вернуть:

+----+-----------+ 
| id | col1  | 
+----+-----------+ 
| 1 | ref_val_1 | 
| 2 | ref_val_2 | 
+----+-----------+ 

Можно ли это сделать с помощью оператора MySQL?

+0

использование 'distinct'. вы получаете избыточные строки из-за отношений «один-много». –

+0

@vkp Является ли мой подход менее эффективным или есть лучший способ сделать это? – nautical

ответ

0

Как уже прокомментировали использование distinct получить уникальное сочетание результатов, а также перемещать эти условия от WHERE пункта до JOIN ON состояния как

SELECT distinct subtable2.* 
FROM zzz_dummy.subtable2 
    INNER JOIN zzz_dummy.subtable1 
    ON zzz_dummy.subtable1.ref_subtab2 = zzz_dummy.subtable2.id 
    INNER JOIN zzz_dummy.maintable 
ON zzz_dummy.maintable.ref_subtab1 = zzz_dummy.subtable1.id; 
Смежные вопросы