MySQL LEFT JOIN 与 ON 子句中的一列

标签 mysql

有一个查询需要优化,查询如下所示:

SELECT *
FROM TableA
LEFT JOIN TableB ON TableA.column_1 = TableB.column_1
  AND TableB.column_2 IS NOT NULL
  AND TableB.column_3 IS NULL
  AND TableB.column_4 IS NULL
  AND TableB.column_5 IS NULL
LEFT JOIN TableC ON TableA.column_1 = TableC.column_1
  AND TableC.column_3 IS NULL
  AND TableC.column_4 IS NULL
  AND TableC.column_5 IS NULL

查询中较慢的部分是 ON 子句中的大量 IS NULL。执行时间约为 4 秒以上。在查询了一段时间后,我注意到 IS NULL 可以从 ON 子句中的字段中省略。像这样:

SELECT *
FROM TableA
LEFT JOIN TableB ON TableA.column_1 = TableB.column_1
  AND TableB.column_2 IS NOT NULL
  AND TableB.column_3
  AND TableB.column_4
  AND TableB.column_5
LEFT JOIN TableC ON TableA.column_1 = TableC.column_1
  AND TableC.column_3
  AND TableC.column_4
  AND TableC.column_5

此查询的执行时间为 53ms!,记录集也与第一个查询相同。试图谷歌它并没有找到任何东西。

有人知道它是如何工作的吗?

MySQL 版本为 5.7.25

更新

CREATE TABLE TableA (
    `column_1` INT(2) NOT NULL,
    `column_2` datetime  NULL,
    `column_3` datetime  NULL,
    `column_4` datetime  NULL,
    `column_5` datetime  NULL,
)

CREATE TABLE TableB (
    `column_1` INT(2) NOT NULL,
    `column_2` datetime  NULL,
    `column_3` datetime  NULL,
    `column_4` datetime  NULL,
    `column_5` datetime  NULL,
)

CREATE TABLE TableC (
    `column_1` INT(2) NOT NULL,
    `column_2` datetime  NULL,
    `column_3` datetime  NULL,
    `column_4` datetime  NULL,
    `column_5` datetime  NULL,
)

INSERT INTO `TableA` (`column_1`, `column_2`, `column_3`, `column_4`, `column_5`)
VALUES
    (1, '2019-08-13 00:00:00', NULL, NULL, NULL);

不包括索引,但是在ON子句中使用的每个字段都有索引

最佳答案

考虑表格:

create table tablename (id int, col datetime);
insert into tablename (id, col) values
(5,   null),
(6,   '2019-01-06 11:38:41'),
(7,   '2019-01-06 11:39:40'),
(8,   '2019-01-06 11:39:49');

查询:

select * 
from tablename
where col 

返回:

| id  | col                 |
| --- | ------------------- |
| 6   | 2019-01-06 11:38:41 |
| 7   | 2019-01-06 11:39:40 |
| 8   | 2019-01-06 11:39:49 |

参见 demo .
这意味着为了将 col 评估为 0 (False) 或 1 (True) 的值,因为评估发生在 WHERE 子句,MySql 将任何 非 null 日期时间值转换为正数 >0,评估为 True 和任何 null value 将评估为 not True(因此被视为 False)。

你描述的恰恰相反。
因为 TableB.column_3 IS NULL 而只是 TableB.column_3 中评估为 >00 >WHEREON 子句返回相反的结果。

关于MySQL LEFT JOIN 与 ON 子句中的一列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57478872/

相关文章:

javascript - PHP 项目的客户端验证是好是坏?以及如何完善PHP项目?

php - 你会因为保存tinyMCE、QuillJS等文本编辑器生成的HTML代码而被黑客攻击吗?

PHP/HTML 表单进入数据库复选框验证

php - mysql 从两个不同的表中选择。

php - MySQL 查询选择除最新日期时间以外的所有日期时间

mysql - 分组依据中的零匹配显示

android - 从 MySQL 数据库向 RecyclerView 添加数据

php - 使用 PHP 和 MySQL 处理用户帐户使用情况

mysql - 在 MySQL 中相等真的意味着相等吗?

具有并发读取和写入的 Mysql 查询性能