为啥 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的区别

Sql_join left right

MYSQL LEFT JOIN 将所有数据返回为 NULL

GROUP_CONCAT 和 LEFT_JOIN 问题 - 并非所有行都返回

为啥这个 LEFT OUTER JOIN 不包括左侧的所有主键