Как сделать несколько правильных объединений в одной команде для разных дочерних таблиц?

Aug 17 2020

На следующем изображении вы видите 3 таблицы: A, B, C. A: это таблица, в которой хранятся внешние ключи от B и C

Если я выполняю правильное соединение между A и B на этом внешнем ключе, он работает, то есть я получаю данные из столбца fooB. То же самое между A и C с fooC.

Но если я поместил оба правых соединения под одну и ту же команду, он не сработает с нулем

+-------------+---------------+
| fooB        | fooC          |
+-------------+---------------+
| NULL        | abc           |
| NULL        | xyz           |

* Это немного отличается от изображения с командами, размещенными ниже, поскольку это происходит прямо из реального развертывания, однако приведенные ниже команды по-прежнему показывают, что оба столбца не отображаются.

Я пробовал смешивать левые соединения, правые соединения, внешние соединения с тем же результатом. Я погуглил об этом, но формулировка моего вопроса неудобна, и полученные мной обращения возвращают традиционные правильные соединения только для одной таблицы.

Как заставить это работать одной командой? CMDS ниже:

Те же команды, что и выше, но в тексте, поскольку в комментариях запрашивается текст, а не изображения:

MariaDB [joinPOC]> select fooB from tableA right join tableB on tableB_idtableB=tableB.idtableB;
+------+
| fooB |
+------+
| b1   |
| b2   |
| b3   |
+------+
3 rows in set (0.001 sec)

MariaDB [joinPOC]> select fooC from tableA right join tableC on tableC_idtableC=tableC.idtableC;
+------+
| fooC |
+------+
| c1   |
| c2   |
| c3   |
+------+
3 rows in set (0.001 sec)

MariaDB [joinPOC]> select fooB from tableA right join tableB on tableB_idtableB=tableB.idtableB right join tableC on tableC_idtableC=tableC.idtableC;
+------+
| fooB |
+------+
| b1   |
| b2   |
| b3   |
+------+

--ЗДЕСЬ ВЕСЬ СЦЕНАРИЙ -

-- MySQL Workbench Forward Engineering

SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION';

-- -----------------------------------------------------
-- Schema joinPOC
-- -----------------------------------------------------
DROP SCHEMA IF EXISTS `joinPOC` ;

-- -----------------------------------------------------
-- Schema joinPOC
-- -----------------------------------------------------
CREATE SCHEMA IF NOT EXISTS `joinPOC` ;
USE `joinPOC` ;

-- -----------------------------------------------------
-- Table `joinPOC`.`tableB`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `joinPOC`.`tableB` (
  `idtableB` INT NOT NULL,
  `fooB` VARCHAR(10) NOT NULL,
  PRIMARY KEY (`idtableB`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `joinPOC`.`tableC`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `joinPOC`.`tableC` (
  `idtableC` INT NOT NULL,
  `fooC` VARCHAR(10) NOT NULL,
  PRIMARY KEY (`idtableC`))
ENGINE = InnoDB;


-- -----------------------------------------------------
-- Table `joinPOC`.`tableA`
-- -----------------------------------------------------
CREATE TABLE IF NOT EXISTS `joinPOC`.`tableA` (
  `idtableA` INT NOT NULL,
  `fooA` VARCHAR(10) NOT NULL,
  `tableB_idtableB` INT NOT NULL,
  `tableC_idtableC` INT NOT NULL,
  PRIMARY KEY (`idtableA`),
  INDEX `fk_tableA_tableB_idx` (`tableB_idtableB` ASC),
  INDEX `fk_tableA_tableC1_idx` (`tableC_idtableC` ASC),
  CONSTRAINT `fk_tableA_tableB`
    FOREIGN KEY (`tableB_idtableB`)
    REFERENCES `joinPOC`.`tableB` (`idtableB`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT `fk_tableA_tableC1`
    FOREIGN KEY (`tableC_idtableC`)
    REFERENCES `joinPOC`.`tableC` (`idtableC`)
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;


SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;

-- -----------------------------------------------------
-- Data for table `joinPOC`.`tableB`
-- -----------------------------------------------------
START TRANSACTION;
USE `joinPOC`;
INSERT INTO `joinPOC`.`tableB` (`idtableB`, `fooB`) VALUES (1, 'b1');
INSERT INTO `joinPOC`.`tableB` (`idtableB`, `fooB`) VALUES (2, 'b2');
INSERT INTO `joinPOC`.`tableB` (`idtableB`, `fooB`) VALUES (3, 'b3');

COMMIT;


-- -----------------------------------------------------
-- Data for table `joinPOC`.`tableC`
-- -----------------------------------------------------
START TRANSACTION;
USE `joinPOC`;
INSERT INTO `joinPOC`.`tableC` (`idtableC`, `fooC`) VALUES (1, 'c1');
INSERT INTO `joinPOC`.`tableC` (`idtableC`, `fooC`) VALUES (2, 'c2');
INSERT INTO `joinPOC`.`tableC` (`idtableC`, `fooC`) VALUES (3, 'c3');

COMMIT;


-- -----------------------------------------------------
-- Data for table `joinPOC`.`tableA`
-- -----------------------------------------------------
START TRANSACTION;
USE `joinPOC`;
INSERT INTO `joinPOC`.`tableA` (`idtableA`, `fooA`, `tableB_idtableB`, `tableC_idtableC`) VALUES (1, 'a1', 1, 1);
INSERT INTO `joinPOC`.`tableA` (`idtableA`, `fooA`, `tableB_idtableB`, `tableC_idtableC`) VALUES (2, 'a2', 2, 2);
INSERT INTO `joinPOC`.`tableA` (`idtableA`, `fooA`, `tableB_idtableB`, `tableC_idtableC`) VALUES (3, 'a3', 3, 3);

COMMIT;

Желаемый результат в одной команде:

+-------------+---------------+
| fooB        | fooC          |
+-------------+---------------+
| b1          | c1            |
| b2          | c2            |

Ответы

1 nbk Aug 17 2020 at 05:22

Вам нужно ВНУТРЕННЕЕ СОЕДИНЕНИЕ.

Чтобы исключить строки, вы можете использовать обычное предложение WHERE или сделать это в предложении ON

Схема (MySQL v8.0)


Запрос №1

SELECT 
    b.fooB, c.fooC
FROM
    tableA a
        INNER JOIN
    tableB b ON a.tableB_idtableB = b.idtableB
        INNER JOIN
    tableC c ON a.tableC_idtableC = c.idtableC;

| fooB | fooC |
| ---- | ---- |
| b1   | c1   |
| b2   | c2   |
| b3   | c3   |

Посмотреть на DB Fiddle