MySQL 带 where 子句的左外连接
MySQL Left outer join with where clause
我正在尝试使用以下 MySQL 查询:
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline AS l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
WHERE l.account_no = 32049 OR l.account_no IS NULL
然而,这 return 没有行,因为 last_24_topline 中没有匹配的 account_no 行。根据我的理解和阅读,这个查询应该仍然 return 来自 top_lines 的所有行,即使 last_24_topline 中没有匹配的行,因为我正在检查一个值或 null,但是它不是。 MySQL (5.7.2) 中是否有任何选项或设置会导致此行为?
仅供参考,此查询按预期工作:
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
AND l.`account_no` = 32049
我无法使用此构造,但是因为我使用的是 entity framework 并且您只能将列而不是值传递给连接
CREATE TABLE `last_24_topline` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`member_no` varchar(30) NOT NULL,
`branch_no` int(11) DEFAULT NULL,
`employee_no` varchar(25) DEFAULT NULL,
`account_no` varchar(25) DEFAULT NULL,
`salesperson_name` varchar(255) DEFAULT NULL,
`customer_name` varchar(255) DEFAULT NULL,
`mfg` varchar(5) DEFAULT NULL,
`mfg_description` varchar(255) DEFAULT NULL,
`last_three` decimal(10,2) DEFAULT '0.00',
`last_twelve` decimal(10,2) DEFAULT '0.00',
`ly_last_three` decimal(10,2) DEFAULT '0.00',
`ly_last_twelve` decimal(10,2) DEFAULT '0.00',
PRIMARY KEY (`id`),
KEY `ix_branch_no` (`branch_no`),
KEY `ix_employee_no` (`employee_no`),
KEY `ix_member_line_account` (`member_no`,`mfg`,`account_no`),
KEY `ix_member_line` (`member_no`,`mfg`),
KEY `ix_account_no` (`account_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `top_lines` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`member_no` varchar(30) NOT NULL,
`line_no` varchar(5) NOT NULL,
`line_description` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_line_no` (`member_no`,`line_no`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=latin1
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (1,'520','772','FED ROTOR/DRUM');
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (2,'520','952','FED SST CERAMIC');
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (3,'520','954','FED SST FRICTION');
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (4,'520','162','EVS FRICTION');
INSERT INTO `last_24_topline` (`id`, `member_no`, `branch_no`, `employee_no`, `account_no`, `salesperson_name`, `customer_name`, `mfg`, `mfg_description`, `last_three`, `last_twelve`, `ly_last_three`, `ly_last_twelve`) VALUES('1','520','0','10856','463854','FORD, JAMES,','JIFFY LUBE','459','FEDERATED AIR FILTER','0.00','15.21','0.00','0.00');
INSERT INTO `last_24_topline` (`id`, `member_no`, `branch_no`, `employee_no`, `account_no`, `salesperson_name`, `customer_name`, `mfg`, `mfg_description`, `last_three`, `last_twelve`, `ly_last_three`, `ly_last_twelve`) VALUES('2','520','0','10856','463854','FORD, JAMES,','JIFFY LUBE','460','FILTERS','0.00','0.00','0.00','16.48');
INSERT INTO `last_24_topline` (`id`, `member_no`, `branch_no`, `employee_no`, `account_no`, `salesperson_name`, `customer_name`, `mfg`, `mfg_description`, `last_three`, `last_twelve`, `ly_last_three`, `ly_last_twelve`) VALUES('3','520','0','10856','463854','FORD, JAMES,','JIFFY LUBE','863','SMP T SERIES','0.00','0.00','0.00','50.67');
我希望,即使 last_24_topline 中没有匹配的数据,第一个查询也会生成一个结果集,其中包含 top_lines 中的所有行,并且 [=] 中的列的值为空35=].
预期结果:
因此,在另一个数据库中创建相同的模式并仅插入我上面提供的示例数据,我得到了预期的结果。我正在通过将完整行复制到第二个数据库来进一步测试,看看它是否仍然提供预期的结果。
更新
将所有数据复制到新表中会导致问题再次出现。我正在尝试将重现该问题所需的最低限度减少。
使用连接中涉及的列而不是 l.account_no
这样,如果左侧 table.[=13= 中没有匹配的行,将返回来自 top_lines 的行]
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline AS l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
WHERE l.account_no = 32049 OR l.`member_no` IS NULL
或者将帐号过滤器直接放入连接
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline AS l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
AND l.account_no = 32049
也尝试检测空字符串,也许字段不是 NULL,而是空字符串。
SELECT *
FROM
top_lines t
LEFT JOIN
last_24_topline AS l ON l.member_no = t.member_no AND l.mfg = t.line_no
WHERE
(l.account_no = '' OR l.account_no = '32049' OR l.account_no IS NULL)
如果您需要更多帮助,我需要 "table last_24_topline" 的样本数据和加入后的预期输出。
作为第二次尝试,您可以使用这个:
SELECT *
FROM
top_lines t
LEFT JOIN
last_24_topline AS l ON l.member_no = t.member_no AND l.mfg = t.line_no
WHERE
l.id IS NULL
OR
(l.id IS NOT NULL AND l.account_no = '32049')
在联接中没有帐号的查询中,联接 确实 匹配 last_24_toplines table 中的行,但它 不匹配where子句中的帐号,因此它被过滤掉并且不被视为来自top_lines的行没有来自last_24_topline.
的匹配行
因此,例如 top_line table
中的这一行
将匹配 last_24_toplines
中的这一行
但两者都将被过滤掉,因为 account_no 与 where 子句中的内容不匹配:WHERE l.account_no = 32049 OR l.account_no IS NULL
在联接中检查 account_no 的查询仍将匹配来自 top_line 的行,但 不会 具有来自 last_24_topline,所以你会得到一行 top_lines 数据,其中 last_24_topline.
我正在尝试使用以下 MySQL 查询:
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline AS l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
WHERE l.account_no = 32049 OR l.account_no IS NULL
然而,这 return 没有行,因为 last_24_topline 中没有匹配的 account_no 行。根据我的理解和阅读,这个查询应该仍然 return 来自 top_lines 的所有行,即使 last_24_topline 中没有匹配的行,因为我正在检查一个值或 null,但是它不是。 MySQL (5.7.2) 中是否有任何选项或设置会导致此行为? 仅供参考,此查询按预期工作:
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
AND l.`account_no` = 32049
我无法使用此构造,但是因为我使用的是 entity framework 并且您只能将列而不是值传递给连接
CREATE TABLE `last_24_topline` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`member_no` varchar(30) NOT NULL,
`branch_no` int(11) DEFAULT NULL,
`employee_no` varchar(25) DEFAULT NULL,
`account_no` varchar(25) DEFAULT NULL,
`salesperson_name` varchar(255) DEFAULT NULL,
`customer_name` varchar(255) DEFAULT NULL,
`mfg` varchar(5) DEFAULT NULL,
`mfg_description` varchar(255) DEFAULT NULL,
`last_three` decimal(10,2) DEFAULT '0.00',
`last_twelve` decimal(10,2) DEFAULT '0.00',
`ly_last_three` decimal(10,2) DEFAULT '0.00',
`ly_last_twelve` decimal(10,2) DEFAULT '0.00',
PRIMARY KEY (`id`),
KEY `ix_branch_no` (`branch_no`),
KEY `ix_employee_no` (`employee_no`),
KEY `ix_member_line_account` (`member_no`,`mfg`,`account_no`),
KEY `ix_member_line` (`member_no`,`mfg`),
KEY `ix_account_no` (`account_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `top_lines` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`member_no` varchar(30) NOT NULL,
`line_no` varchar(5) NOT NULL,
`line_description` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `ix_line_no` (`member_no`,`line_no`)
) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=latin1
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (1,'520','772','FED ROTOR/DRUM');
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (2,'520','952','FED SST CERAMIC');
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (3,'520','954','FED SST FRICTION');
insert into `top_lines`(`id`,`member_no`,`line_no`,`line_description`) values (4,'520','162','EVS FRICTION');
INSERT INTO `last_24_topline` (`id`, `member_no`, `branch_no`, `employee_no`, `account_no`, `salesperson_name`, `customer_name`, `mfg`, `mfg_description`, `last_three`, `last_twelve`, `ly_last_three`, `ly_last_twelve`) VALUES('1','520','0','10856','463854','FORD, JAMES,','JIFFY LUBE','459','FEDERATED AIR FILTER','0.00','15.21','0.00','0.00');
INSERT INTO `last_24_topline` (`id`, `member_no`, `branch_no`, `employee_no`, `account_no`, `salesperson_name`, `customer_name`, `mfg`, `mfg_description`, `last_three`, `last_twelve`, `ly_last_three`, `ly_last_twelve`) VALUES('2','520','0','10856','463854','FORD, JAMES,','JIFFY LUBE','460','FILTERS','0.00','0.00','0.00','16.48');
INSERT INTO `last_24_topline` (`id`, `member_no`, `branch_no`, `employee_no`, `account_no`, `salesperson_name`, `customer_name`, `mfg`, `mfg_description`, `last_three`, `last_twelve`, `ly_last_three`, `ly_last_twelve`) VALUES('3','520','0','10856','463854','FORD, JAMES,','JIFFY LUBE','863','SMP T SERIES','0.00','0.00','0.00','50.67');
我希望,即使 last_24_topline 中没有匹配的数据,第一个查询也会生成一个结果集,其中包含 top_lines 中的所有行,并且 [=] 中的列的值为空35=].
预期结果:
因此,在另一个数据库中创建相同的模式并仅插入我上面提供的示例数据,我得到了预期的结果。我正在通过将完整行复制到第二个数据库来进一步测试,看看它是否仍然提供预期的结果。
更新 将所有数据复制到新表中会导致问题再次出现。我正在尝试将重现该问题所需的最低限度减少。
使用连接中涉及的列而不是 l.account_no
这样,如果左侧 table.[=13= 中没有匹配的行,将返回来自 top_lines 的行]
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline AS l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
WHERE l.account_no = 32049 OR l.`member_no` IS NULL
或者将帐号过滤器直接放入连接
SELECT *
FROM top_lines t
LEFT OUTER JOIN last_24_topline AS l ON l.`member_no` = t.`member_no`
AND l.`mfg` = t.`line_no`
AND l.account_no = 32049
也尝试检测空字符串,也许字段不是 NULL,而是空字符串。
SELECT *
FROM
top_lines t
LEFT JOIN
last_24_topline AS l ON l.member_no = t.member_no AND l.mfg = t.line_no
WHERE
(l.account_no = '' OR l.account_no = '32049' OR l.account_no IS NULL)
如果您需要更多帮助,我需要 "table last_24_topline" 的样本数据和加入后的预期输出。
作为第二次尝试,您可以使用这个:
SELECT *
FROM
top_lines t
LEFT JOIN
last_24_topline AS l ON l.member_no = t.member_no AND l.mfg = t.line_no
WHERE
l.id IS NULL
OR
(l.id IS NOT NULL AND l.account_no = '32049')
在联接中没有帐号的查询中,联接 确实 匹配 last_24_toplines table 中的行,但它 不匹配where子句中的帐号,因此它被过滤掉并且不被视为来自top_lines的行没有来自last_24_topline.
的匹配行因此,例如 top_line table
中的这一行将匹配 last_24_toplines
中的这一行但两者都将被过滤掉,因为 account_no 与 where 子句中的内容不匹配:WHERE l.account_no = 32049 OR l.account_no IS NULL
在联接中检查 account_no 的查询仍将匹配来自 top_line 的行,但 不会 具有来自 last_24_topline,所以你会得到一行 top_lines 数据,其中 last_24_topline.