两个子表的 MySQL JOIN 问题

Posted

技术标签:

【中文标题】两个子表的 MySQL JOIN 问题【英文标题】:MySQL JOIN problems with two child tables 【发布时间】:2012-02-09 21:11:44 【问题描述】:

我现在正在学习 mysql JOIN,我想知道的一件事是如何将两个子表与一个父表 JOIN。

在这种情况下,查询是这样的:

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='TRADITIONAL';

DROP SCHEMA IF EXISTS `test` ;

CREATE SCHEMA IF NOT EXISTS `test` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;

USE `test`;

CREATE  TABLE IF NOT EXISTS `test`.`objetos` (
  `idobjetos` INT(11) NOT NULL AUTO_INCREMENT ,
  `modelo` VARCHAR(45) NULL DEFAULT NULL ,
  `descricao` VARCHAR(45) NULL DEFAULT NULL ,
  `token_dono` VARCHAR(41) NOT NULL ,
  PRIMARY KEY (`idobjetos`, `token_dono`) ,
  INDEX `token_dono` (`token_dono` ASC) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

CREATE  TABLE IF NOT EXISTS `test`.`empresas` (
  `idempresa` INT(11) NULL DEFAULT NULL AUTO_INCREMENT ,
  `nome` VARCHAR(45) NULL DEFAULT NULL ,
  `cnpj` VARCHAR(45) NULL DEFAULT NULL ,
  `email` VARCHAR(45) NULL DEFAULT NULL ,
  `telefone` VARCHAR(45) NULL DEFAULT NULL ,
  `token` VARCHAR(41) NOT NULL ,
  PRIMARY KEY (`idempresa`, `token`) ,
  INDEX `token_empresa` (`token` ASC) ,
  UNIQUE INDEX `cnpj_UNIQUE` (`cnpj` ASC) ,
  UNIQUE INDEX `email_UNIQUE` (`email` ASC) ,
  UNIQUE INDEX `telefone_UNIQUE` (`telefone` ASC) ,
  CONSTRAINT `token_empresa`
    FOREIGN KEY (`token` )
    REFERENCES `test`.`objetos` (`token_dono` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

CREATE  TABLE IF NOT EXISTS `test`.`civis` (
  `idcivil` INT(11) NOT NULL AUTO_INCREMENT ,
  `nome` VARCHAR(45) NULL DEFAULT NULL ,
  `cpf` VARCHAR(45) NULL DEFAULT NULL ,
  `email` VARCHAR(45) NULL DEFAULT NULL ,
  `token` VARCHAR(41) NOT NULL ,
  PRIMARY KEY (`idcivil`, `token`) ,
  INDEX `token_civil` (`token` ASC) ,
  UNIQUE INDEX `cpf_UNIQUE` (`cpf` ASC) ,
  UNIQUE INDEX `email_UNIQUE` (`email` ASC) ,
  CONSTRAINT `token_civil`
    FOREIGN KEY (`token` )
    REFERENCES `test`.`objetos` (`token_dono` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

CREATE  TABLE IF NOT EXISTS `test`.`an_users` (
  `id` INT(11) NULL DEFAULT NULL AUTO_INCREMENT ,
  `usuario` VARCHAR(45) NULL DEFAULT NULL ,
  `senha` VARCHAR(45) NULL DEFAULT NULL ,
  `cod_usuario` INT(11) NOT NULL ,
  PRIMARY KEY (`id`, `cod_usuario`) ,
  INDEX `cod_usuario_fk` (`cod_usuario` ASC) ,
  CONSTRAINT `cod_usuario_fk`
    FOREIGN KEY (`cod_usuario` )
    REFERENCES `test`.`empresas` (`idempresa` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;


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

我已经插入了这些值:

INSERT INTO `mydb`.`objetos` VALUES (NULL, 'Cadeira XTT', 'Quê?', SHA1(CONCAT(3913123612,'one@gmail.com')));
INSERT INTO `mydb`.`objetos` VALUES (NULL, 'Mesa TTX', 'Hein?', SHA1(CONCAT(4313123612,'two@gmail.com')));
INSERT INTO `mydb`.`objetos` VALUES (NULL, 'Prédio TT', 'Hein?', SHA1(CONCAT(73358847000116,'buzz@gmail.com')));

INSERT INTO `mydb`.`civis` VALUES (NULL, 'One', 3913123612, 'one@gmail.com', SHA1(CONCAT(3913123612,'one@gmail.com')));
INSERT INTO `mydb`.`civis` VALUES (NULL, 'Two', 4313123612, 'two@gmail.com', SHA1(CONCAT(4313123612,'two@gmail.com')));

INSERT INTO `mydb`.`empresas` VALUES(NULL, 'Buzz', 73358847000116, 'buzz@gmail.com', 33270743, SHA1(CONCAT(73358847000116,'buzz@gmail.com')));

但是当我想检索记录的数据时出现了一些问题。 NATURAL JOIN 没有按预期工作,只采用具有相同标记的行,我不能这样做:

SELECT * 
FROM objetos 

JOIN civis 
ON(objetos.token_dono = civis.token) 

JOIN empresas 
ON(objetos.token_dono = empresas.token)

从数据库中列出所有带有正确信息的“objetos”。但正如我测试过的那样,它不起作用。

如果有人能帮我解决这些问题,我将不胜感激。

【问题讨论】:

你可能想要的是左连接 您可以从表格中选择所有内容以确保您以正确的顺序插入值吗? LEFT JOIN 已经起作用,但是当我将它传递给 php 时,我将如何知道我必须采用哪个“nome”列?因为当我进行查询时,列“nome”没有混合,然后我有两列具有相同的标签。 是的,我可以从每个表中选择所有内容,例如,我可以执行 SELECT * FROM objeto JOIN civis。 你能举个例子说明你希望你的结果是什么样的吗? 【参考方案1】:

您遇到的情况是,不合格的JOIN 实际上被解释为INNER JOIN,有关详细信息,请参阅documentation。

因此,当您运行查询时,不包含来自objetos 的匹配token 的行将被删除,然后由于来自civis 的任何标记都与来自empresastoken 不匹配,因此所有行都将被删除。

因此,从我收集到的你正在尝试做的事情来看,如果你想从所有表中获取所有列或将这个查询分开,那么你实际上需要做一个LEFT JOIN

SELECT * FROM objetos o JOIN civis c ON (o.token_dono = c.token);

SELECT * FROM objetos o JOIN empresas e ON (o.token_dono = e.token);

【讨论】:

我用它和 UNION 来制作我想要的东西。谢谢大家。

以上是关于两个子表的 MySQL JOIN 问题的主要内容,如果未能解决你的问题,请参考以下文章

如何基于跨两个表的数学运算对条件执行 MySQL JOIN?

MySQL JOIN 2 个表并分别获取两个表的总和

基于条件比较两个子表的聚合返回记录

无法向作为两个嵌套关系中的子表的 DataTable 添加约束

SQL 如何把两个表相关联的数据一同删除

mysql中inner join和outer join有啥区别?