Como fazer várias junções à direita em um único comando para diferentes tabelas filhas?

Aug 17 2020

Na imagem a seguir você vê 3 tabelas: A, B , C. A: É a tabela que contém as chaves estrangeiras de B e C

Se eu fizer uma junção correta entre A e B nessa chave estrangeira, funcionará, o que significa que obtenho os dados da coluna fooB. O mesmo entre A e C com fooC.

Mas se eu colocar as duas junções corretas sob o mesmo comando, ele falhará com nulo

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

*Isso é um pouco diferente da imagem com os comandos postados abaixo, pois vem direto da implantação real, porém os cmds abaixo ainda mostram que as duas colunas não aparecem.

Eu tentei misturar junções esquerdas, junções direitas, junções externas, todas com o mesmo resultado. Pesquisei sobre isso no Google, mas a forma como minha pergunta é formulada é estranha e os resultados que recebo retornam as junções corretas tradicionais para apenas uma tabela.

Como faço para que isso funcione em um comando? CMDS abaixo:

Mesmos comandos acima, mas em texto, pois os comentários solicitam texto em vez de imagens:

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   |
+------+

--AQUI ESTÁ O SCRIPT COMPLETO--

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

Saída desejada em um único comando:

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

Respostas

1 nbk Aug 17 2020 at 05:22

O que você quer é um INNER JOIN.

Para excluir linhas, você pode usar a cláusula WHERE normal ou fazê-lo na cláusula ON

Esquema (MySQL v8.0)


Consulta #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   |

Ver no DB Fiddle