Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 连接两个表时的左外连接_Mysql_Sql - Fatal编程技术网

Mysql 连接两个表时的左外连接

Mysql 连接两个表时的左外连接,mysql,sql,Mysql,Sql,当连接到第二个表t2的第三个表t3上存在给定条件时,我想将第二个表t2外部连接到第一个表t1。如果该条件不存在,我仍然希望返回第一个表t1中的记录,就像左外部联接通常的工作方式一样 我可能完全把阅读本文的人弄糊涂了,所以我写了两个查询,返回了我想要的结果 一个查询是否比另一个查询更有效?是否有更高效的查询返回相同的结果 说明 ID SELECT_TYPE TABLE TYPE POSSIBLE_KEYS KEY KEY_LEN REF ROWS

当连接到第二个表t2的第三个表t3上存在给定条件时,我想将第二个表t2外部连接到第一个表t1。如果该条件不存在,我仍然希望返回第一个表t1中的记录,就像左外部联接通常的工作方式一样

我可能完全把阅读本文的人弄糊涂了,所以我写了两个查询,返回了我想要的结果

一个查询是否比另一个查询更有效?是否有更高效的查询返回相同的结果

说明

ID  SELECT_TYPE     TABLE   TYPE    POSSIBLE_KEYS   KEY     KEY_LEN     REF     ROWS    EXTRA
1   PRIMARY     t1  ALL     (null)  (null)  (null)  (null)  3   
1   PRIMARY     <derived2>  ALL     (null)  (null)  (null)  (null)  1   
2   DERIVED     t2  index   PRIMARY     fk_table1_t11_idx   4   (null)  3   Using index
2   DERIVED     t3  ALL     PRIMARY     (null)  (null)  (null)  3   Using where; Using join buffer
ID  SELECT_TYPE     TABLE   TYPE    POSSIBLE_KEYS   KEY     KEY_LEN     REF     ROWS    EXTRA
1   PRIMARY     t1  ALL     (null)  (null)  (null)  (null)  3   
1   PRIMARY     <derived2>  ALL     (null)  (null)  (null)  (null)  3   
2   DERIVED     t2  index   PRIMARY     fk_table1_t11_idx   4   (null)  3   Using index
2   DERIVED     t3  ALL     PRIMARY     (null)  (null)  (null)  3   Using where; Using join buffer
说明

ID  SELECT_TYPE     TABLE   TYPE    POSSIBLE_KEYS   KEY     KEY_LEN     REF     ROWS    EXTRA
1   PRIMARY     t1  ALL     (null)  (null)  (null)  (null)  3   
1   PRIMARY     <derived2>  ALL     (null)  (null)  (null)  (null)  1   
2   DERIVED     t2  index   PRIMARY     fk_table1_t11_idx   4   (null)  3   Using index
2   DERIVED     t3  ALL     PRIMARY     (null)  (null)  (null)  3   Using where; Using join buffer
ID  SELECT_TYPE     TABLE   TYPE    POSSIBLE_KEYS   KEY     KEY_LEN     REF     ROWS    EXTRA
1   PRIMARY     t1  ALL     (null)  (null)  (null)  (null)  3   
1   PRIMARY     <derived2>  ALL     (null)  (null)  (null)  (null)  3   
2   DERIVED     t2  index   PRIMARY     fk_table1_t11_idx   4   (null)  3   Using index
2   DERIVED     t3  ALL     PRIMARY     (null)  (null)  (null)  3   Using where; Using join buffer
我的模式如下

CREATE  TABLE IF NOT EXISTS t1 (
  id INT NOT NULL ,
  data VARCHAR(45) NULL ,
  PRIMARY KEY (id) )
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS t3 (
  id INT NOT NULL ,
  fk VARCHAR(45) NULL ,
  PRIMARY KEY (id) )
ENGINE = InnoDB;

CREATE  TABLE IF NOT EXISTS t2 (
  t3_id INT NOT NULL ,
  t1_id INT NOT NULL ,
  data VARCHAR(45) NULL ,
  PRIMARY KEY (t3_id) ,
  INDEX fk_table1_t11_idx (t1_id ASC) ,
  CONSTRAINT fk_table1_t3
    FOREIGN KEY (t3_id )
    REFERENCES t3 (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION,
  CONSTRAINT fk_table1_t11
    FOREIGN KEY (t1_id )
    REFERENCES t1 (id )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB;

INSERT INTO t1(id,data) VALUES (1,'blue');
INSERT INTO t1(id,data) VALUES (2,'red');
INSERT INTO t1(id,data) VALUES (3,'green');

INSERT INTO t3(id,fk) VALUES (1,123);
INSERT INTO t3(id,fk) VALUES (2,321);
INSERT INTO t3(id,fk) VALUES (3,321);

INSERT INTO t2(t1_id,t3_id,data) VALUES (1,1,'dog');
INSERT INTO t2(t1_id,t3_id,data) VALUES (2,2,'Cat');
INSERT INTO t2(t1_id,t3_id,data) VALUES (2,3,'Bird');

现在已经很晚了,所以我可能把事情搞砸了。但是,您必须更正t3.id=td.t3\u id上的条件,因为我没有看到任何名为td的表。。。在您的代码和我的代码中:

SELECT t1.*,t2.t1_id,t3.fk
FROM t1
LEFT OUTER JOIN t2 ON t2.t1_id=t1.id
LEFT JOIN t3 ON t3.id=td.t3_id -- please update this condition
WHERE t3.fk=123
阅读上面的评论,你可能更希望看到这样的东西:

SELECT t1.*,t2.t1_id,t3.fk
FROM t1
LEFT OUTER JOIN t2 ON t2.t1_id=t1.id
LEFT JOIN t3 ON t3.id=td.t3_id AND t3.fk=123 -- please update this condition
一个查询是否比另一个查询更有效

不,它们生成相同的查询计划,因此它们应该具有相同的性能。不假设可以从查询缓存或InnoDB缓冲池获取结果

是否有更高效的查询返回相同的结果

你确实问过,这个问题可能会把你推向正确的方向。。。 因为我不能完全确定你是否需要这个

SELECT
  t1.id
, t1.data
, IF(t3.fk IS NULL, NULL, t1.id) "t1_id"
, t3.fk
FROM
  t1

LEFT JOIN (
  SELECT 
    t1_id
  FROM 
    t2
  GROUP BY
    t1_id ASC
)
 t2
ON
 t1.id = t2.t1_id

LEFT JOIN 
 t3
ON
 t3.id = t2.t1_id AND t3.fk = '123'
见演示

上面的查询还解决了查询中的重复问题

需要减少一个派生表,并将类型更改为eq_ref。。这将导致更好的性能,因为可以使用更少的内存进行更好的查找。。请注意,无法删除表t1上的完整表扫描

你的要求/问题

我想将第二个表t2与第一个表t1左外连接 当第三个表t3上存在给定条件时,该表与 第二张表是t2

但对我来说,第一个记录听起来更像是一个关系内部连接,因为这是一个基于条件t3.fk='123'的匹配记录

如果这种情况不存在,我仍然希望 从第一个表t1返回记录,就像左表 JOIN正常工作

下一个记录是表t1中的不匹配项。。。是什么让我想知道,从理论上讲,应该可以编写一个更好的优化查询


待续

添加一些示例和您期望的结果将非常有用。如果不使用子选择,这可能会更快。请尝试对两个查询运行解释计划,并比较输出……我认为查询计划应该是相同的。@Axel。如何不使用子选择?它不会过滤t1吗?@user1032531你说的过滤t1是什么意思?您使用左连接,因此t1中的所有内容都将显示。对不起,td是一个输入错误。我想你的第二个问题可能行得通。我将测试它并发布一个sql fiddle。Axel,请查看我的原始帖子。我将展示这两个查询以及它们如何产生不同的结果。谢谢Ray。上面的查询还解决了查询中的重复问题:被重复的行实际上并没有被重复,因为它包含不同的t3。但对我来说,第一个记录听起来更像是一个关系内部连接,因为这是一个基于条件t3.fk='123'的匹配记录。。但是一个内部连接将过滤掉任何我不想要的未连接的T1。待续。。。期待它。@user1032531确实与您的新sqlfiddle www.sqlfiddle.com/!2/bd56e6/191。新的sqlfiddle显示了您需要的列?是的,我想我得到了我需要的结果,应该保留我的一个原始查询。但是,我不知道是否还有更好的。也许在WHERE子句中,某种条件IF语句在没有连接的情况下不过滤T1?WHERE子句中的IF语句将使该列上的索引无效
SELECT t1.*,t2.t1_id,t3.fk
FROM t1
LEFT OUTER JOIN t2 ON t2.t1_id=t1.id
LEFT JOIN t3 ON t3.id=td.t3_id AND t3.fk=123 -- please update this condition
SELECT
  t1.id
, t1.data
, IF(t3.fk IS NULL, NULL, t1.id) "t1_id"
, t3.fk
FROM
  t1

LEFT JOIN (
  SELECT 
    t1_id
  FROM 
    t2
  GROUP BY
    t1_id ASC
)
 t2
ON
 t1.id = t2.t1_id

LEFT JOIN 
 t3
ON
 t3.id = t2.t1_id AND t3.fk = '123'