Làm cách nào để tạo nhiều phép nối phải trong một lệnh duy nhất cho các bảng con khác nhau?

Aug 17 2020

Trên hình ảnh sau, bạn thấy 3 bảng: A, B, C. A: Là bảng chứa khóa ngoại từ B và C

Nếu tôi thực hiện phép nối phải giữa A và B trên khóa ngoại đó, nó hoạt động, nghĩa là tôi lấy dữ liệu từ cột fooB. Tương tự giữa A và C với fooC.

Nhưng nếu tôi đặt cả hai phép nối bên phải dưới cùng một lệnh, nó không thành công với null

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

* Điều này hơi khác so với hình ảnh với các lệnh được đăng bên dưới, vì điều này đến trực tiếp từ triển khai thực, tuy nhiên các cmds bên dưới vẫn cho thấy rằng cả hai cột không hiển thị.

Tôi đã thử kết hợp các phép nối bên trái, phép nối phải, phép nối bên ngoài, tất cả đều có cùng kết quả. Tôi đã tìm kiếm trên Google về điều này, nhưng cách câu hỏi của tôi được xây dựng rất khó hiểu và các lần truy cập tôi nhận được trả về các phép nối phải truyền thống chỉ cho một bảng.

Làm cách nào để làm cho điều này hoạt động trong một lệnh? CMDS bên dưới:

Các lệnh tương tự như trên nhưng ở dạng văn bản, vì nhận xét yêu cầu văn bản thay vì hình ảnh:

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

- CÓ TOÀN BỘ KHOẢNG CÁCH--

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

Đầu ra mong muốn trong một lệnh duy nhất:

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

Trả lời

1 nbk Aug 17 2020 at 05:22

Những gì bạn muốn là THAM GIA BÊN TRONG.

Để loại trừ các hàng, bạn có thể sử dụng mệnh đề WHERE thông thường hoặc thực hiện trong mệnh đề BẬT

Lược đồ (MySQL v8.0)


Truy vấn số 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   |

Xem trên DB Fiddle