当第三个表t2
上存在给定条件时,我希望将第二个表t1
左键连接到第一个表t3
,该表连接到第二个表t2
1}}。如果该条件不存在,我仍然希望从第一个表t1
返回记录,就像LEFT OUTER JOIN通常如何工作一样。
我可能完全混淆了读这个的人,所以我写了两个回复我想要的结果的查询。
一个查询比另一个更有效吗?是否有更有效的查询返回相同的结果?
http://sqlfiddle.com/#!2/bd56e6/8
SELECT *
FROM t1
LEFT OUTER JOIN
(
SELECT t2.t1_id,t3.fk
FROM t2
INNER JOIN t3 ON t3.id=t2.t3_id
WHERE t3.fk=123
) AS t2 ON t2.t1_id=t1.id
ID DATA T1_ID FK
1 blue 1 123
2 red (null) (null)
3 green (null) (null)
EXPLAIN
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
http://sqlfiddle.com/#!2/bd56e6/5
SELECT *
FROM t1
LEFT OUTER JOIN
(
SELECT t2.t1_id,t3.fk
FROM t2
INNER JOIN t3 ON t3.id=t2.t3_id
) AS t2 ON t2.t1_id=t1.id AND t2.fk=123
ID DATA T1_ID FK
1 blue 1 123
2 red (null) (null)
3 green (null) (null)
EXPLAIN
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
您将看到以下两个查询产生不同的结果:
http://sqlfiddle.com/#!2/bd56e6/9
SELECT *
FROM t1
LEFT OUTER JOIN t2 ON t2.t1_id=t1.id
LEFT OUTER JOIN t3 ON t3.id=t2.t3_id
WHERE t3.fk=123
ID DATA T3_ID T1_ID FK
1 blue 1 1 123
http://sqlfiddle.com/#!2/bd56e6/10
SELECT *
FROM t1
LEFT OUTER JOIN t2 ON t2.t1_id=t1.id
LEFT OUTER JOIN t3 ON t3.id=t2.t3_id AND t3.fk=123
ID DATA T3_ID T1_ID FK
1 blue 1 1 123
2 red 2 2 (null)
2 red 3 2 (null)
3 green (null) (null) (null)
我的架构在下面
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');
答案 0 :(得分:0)
玩这样的东西(已经很晚了,所以我可能会把它搞砸了)。但是,您必须更正条件ON t3.id=td.t3_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
答案 1 :(得分:0)
一个查询是否比另一个更有效?
不会生成相同的查询计划,因此它们应该具有相同的性能。不假设结果可以从查询缓存或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'
参见演示http://sqlfiddle.com/#!2/bd56e6/136
上述查询还解决了查询中的重复http://sqlfiddle.com/#!2/bd56e6/173
需要少一个派生表,并且类型更改为eq_ref ..这将导致更好的性能,因为可以用更少的内存进行更好的查找..请注意,无法删除全表扫描在表t1 ..
您的要求/问题..
我想LEFT OUTER JOIN第二个表t2到第一个表t1 当给定条件存在于第三个表t3上时,该表连接到 第二个表t2。
但是第一条记录听起来更像是对我的关系(INNER JOIN),因为这是一个基于条件t3.fk ='123'的匹配记录。
如果不存在这种情况,我仍然希望 返回第一个表t1中的记录,就像LEFT OUTER一样 JOIN通常有效。
接下来的记录是来自表t1的非匹配...让我想知道它应该可以编写一个更好的优化查询...
继续......