为啥 MySQL LEFT JOIN 不返回所有行,除非有 WHERE 子句 - phpMyAdmin 问题
Posted
技术标签:
【中文标题】为啥 MySQL LEFT JOIN 不返回所有行,除非有 WHERE 子句 - phpMyAdmin 问题【英文标题】:Why does MySQL LEFT JOIN not return all rows unless there is WHERE clause - phpMyAdmin issue为什么 MySQL LEFT JOIN 不返回所有行,除非有 WHERE 子句 - phpMyAdmin 问题 【发布时间】:2014-02-14 21:54:15 【问题描述】:考虑以下几点:
eventTypes 表有 163 行。
事件有 43,000 行。
SELECT events.eventTypeID, eventTypes.eventTypeName
FROM events
LEFT JOIN eventTypes ON events.eventTypeID = eventTypes.eventTypeID
这将返回 163 行。但是,如果我添加“WHERE events.eventID >= 0”
SELECT events.eventTypeID, eventTypes.eventTypeName
FROM events
LEFT JOIN eventTypes ON events.eventTypeID = eventTypes.eventTypeID
WHERE events.eventID >= 0
我得到了所有 43,000 行。我希望缺少 WHERE 子句会给我一切。我是不是想错了?
更新:我刚刚在另一台服务器上尝试过,结果相同。我复制并粘贴的确切查询是:
SELECT events.eventTypeID, eventTypes.eventTypeName FROM events LEFT JOIN eventTypes ON events.eventTypeID = eventTypes.eventTypeID
这只会返回前 163 条记录。 mysql 版本为 5.5.29 和 5.1.61。我查看了错误列表,没有发现任何内容。
更新 #2:EXPLAIN 给出与任一查询相同的输出(即有或没有 WHERE 1=1)
mysql> EXPLAIN(SELECT events.eventTypeID, eventTypes.eventTypeName FROM events LEFT JOIN eventTypes ON events.eventTypeID = eventTypes.eventTypeID);
+----+-------------+------------+--------+---------------+-------------+---------+-------------------------------+-------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+---------------+-------------+---------+-------------------------------+-------+-------------+
| 1 | SIMPLE | events | index | NULL | eventTypeID | 4 | NULL | 37748 | Using index |
| 1 | SIMPLE | eventTypes | eq_ref | PRIMARY | PRIMARY | 4 | casefriend.events.eventTypeID | 1 | |
+----+-------------+------------+--------+---------------+-------------+---------+-------------------------------+-------+-------------+
Update#3 在第三个系统上进行测试会产生我期望的结果,尽管我不知道为什么。第三个系统是另一个运行 MySQL 5.1.69 的 CentOS6。我从我的开发系统中导入了准确的转储,这些转储导入到第二个测试系统中,但没有产生正确的结果。
Update#4 发现问题。这不是 MySQL 问题。这是一个 phpMyAdmin 问题。使用 mysql 客户端在命令行上进行测试时,我在所有系统上都得到了正确的结果。
【问题讨论】:
WHERE 1=1
提供了什么? :)
您的查询有问题。您不能添加 where
子句并获得更多行。
@hobbs WHERE 1=1 也可以。
@GordonLinoff Linoff 我同意,但您正在查看确切的查询。我保证发生的事情是真的。
您的 second 查询是产生正确结果的查询 - 毕竟这是您使用的 LEFT JOIN
。我的猜测是关于表/索引的某些东西导致优化器表现得很有趣(即,改为考虑INNER JOIN
)。因此,您的 WHERE
子句使优化器意识到“伙计,他真的是这个意思”。所以并不是WHERE
子句给了你更多的结果,而是由于某种原因,这种情况给你带来了更少的结果。
【参考方案1】:
I would expect the lack of a WHERE clause would give me everything.
Am I thinking about this wrong?
是的,你是对的,你的第一个查询是正确的,它应该返回你所期望的。
您正在使用 LEFT OUTER JOIN
,这意味着来自左表的所有记录和来自右表的匹配记录。
据我所知,此问题与 MYSQL 版本无关。
我的建议是,请检查您要加入两个表的关系(外键和主键)。
【讨论】:
【参考方案2】:SELECT events.eventTypeID, eventTypes.eventTypeName
FROM events
LEFT JOIN eventTypes ON events.eventTypeID = eventTypes.eventTypeID
WHERE events.eventID >= 0
因为如果您提到 (events.eventID >= 0),这意味着让所有符合此条件的行都为真,并且事件表有 43000 行并且所有行的条件都为真,并且您使用 LEFT JOIN所以你得到 43000 行
【讨论】:
【参考方案3】:我在 SqlFiddle 上试过这个:http://sqlfiddle.com/#!2/c9908b/1
create table event (id int,type_id int);
create table type (type_id int, type_name varchar(30));
insert into type values(1, 'type 1');
insert into type values(2, 'type 2');
insert into type values(3, 'type 3');
insert into type values(4, 'type 4');
insert into type values(5, 'type 5');
insert into event values( 1,1);
insert into event values( 2,1);
insert into event values( 3,1);
insert into event values( 4,1);
insert into event values( 5,2);
insert into event values( 6,2);
insert into event values( 7,2);
insert into event values( 8,2);
insert into event values( 9,3);
insert into event values(10,3);
insert into event values(11,3);
insert into event values(12,3);
insert into event values(13,4);
insert into event values(14,4);
insert into event values(15,4);
insert into event values(16,4);
insert into event values(17,5);
insert into event values(18,5);
insert into event values(19,5);
insert into event values(20,5);
select event.id, type.type_name from event left join type
on event.type_id=type.type_id
我按预期返回了 20 行
【讨论】:
我将您的代码加载到我的数据库中并进行了尝试,它也适用于我的系统。现在要弄清楚我的情况有什么“特别”... 您系统的输出是什么?如果只有 5 行,哪 5 行? 我尽我所能将我的结构和一些数据复制到 sqlfiddle 并保持在 8000 字符的限制内。我确实设法进行了成功的测试,并且它在 sqlfiddle 上确实可以正常工作。 sqlfiddle.com/#!2/6c410/2 所以,我的系统有些奇怪。接下来我会在我猜的第三台服务器上尝试完整的数据集。 什么版本的 MySQL? Linux 还是 Windows?您可以删除并重新安装 MySQL 吗? 我已经在 MySQL 版本 5.5.29 和 5.1.61 上进行了尝试。一个在 Mac 上运行带有 MAMP(开发系统)的 Mountain Lion。另一个在 CentOS6 服务器上。以上是关于为啥 MySQL LEFT JOIN 不返回所有行,除非有 WHERE 子句 - phpMyAdmin 问题的主要内容,如果未能解决你的问题,请参考以下文章
LEFT JOIN 不返回 MS Access 左表中的所有行?
mysql left join,right join,inner join的区别