我的问题是:我的想法出现了什么问题?
为什么左连接不按我想象的那样工作?
A working answer was given (without explanation), here.
更多信息下来。
I have this sql fiddle displaying the problem I am facing when using left outer join
结构
CREATE TABLE IF NOT EXISTS `mychanges` (
`object_id` int(11) unsigned NOT NULL,
`version_stamp` datetime DEFAULT NULL,
`object_name` varchar(255) DEFAULT NULL,
`project` int(11) unsigned DEFAULT NULL,
PRIMARY KEY (`object_id` ,`version_stamp`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO mychanges VALUES (1266, "2014-09-24 09:55:40", "bbbb", 2 );
INSERT INTO mychanges VALUES (1236, "2014-09-24 09:55:40", "aaa", 2 );
INSERT INTO mychanges VALUES (1226, "2014-09-24 09:55:40", "zzz", 5 );
INSERT INTO mychanges VALUES (1216, "2014-09-24 09:55:40", "xxxx", 8 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:51:40", "name1", 10 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:52:40", "name2", 10 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:53:40", "name3", 10 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:54:40", "name4", null );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:56:40", "name5", null );
选择
SELECT mychanges.object_id AS objectid1, mychanges.object_name AS objectname1, mychanges.version_stamp AS version_stamp1, change2.project as project2, change2.version_stamp as version_stamp2, change2.object_name as objectname2 FROM mychanges
LEFT JOIN (SELECT * from mychanges AS x WHERE x.project IS NULL) AS change2
ON change2.object_id = mychanges.object_id
WHERE mychanges.project = 10
我想得到什么:
插入的值
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:51:40", "name1", 10 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:52:40", "name2", 10 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:53:40", "name3", 10 );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:54:40", "name4", null );
INSERT INTO mychanges VALUES (1256, "2014-09-24 09:56:40", "name5", null );
所以在书面语言中:所有记录的项目都是10,所有记录都具有相同的对象id,并且记录的项目标识为10。
为什么?
这是一个变更集表。用户正在更改对象名称并按Enter键。这会以更改的形式生成条目。遗憾的是,这些更改的项目ID为null。对象id虽然是唯一的。
我在想什么?
我想:对了project_id为NULL的所有条目。左边我们有所有记录,其中project_id为10.如果我们使用object_id
加入它们,我们得到两个,没有重复。但是我们得到了name4和name5的重复,而不是name1,name2和name3。
为什么不呢?
答案 0 :(得分:1)
我想:对了project_id为NULL的所有条目。离开了我们 拥有project_id为10的所有记录。如果我们加入它们,我们就会得到 两者都没有重复
否即可。您无法加入,因为值NULL
与其他任何值都不具有可比性,即使与NULL
也不相同。如果您有null,则需要使用ifNULL()
函数显式处理它。
修改强>
第二眼看,我意识到你正在尝试加入object_id
,这当然不是空的。因此,让我们看看您的查询中发生了什么。如果我可以分两部分打破您的查询,第一部分是:
SELECT
mychanges.object_id AS objectid1,
mychanges.object_name AS objectname1,
mychanges.version_stamp AS version_stamp1
FROM mychanges
WHERE mychanges.project = 10
这会产生3条object_id
= 1256
第二部分是,
SELECT * from mychanges AS x WHERE x.project IS NULL
这会产生2条object_id
= 1256的记录。
当您使用条件change2.object_id = mychanges.object_id
连接这两个部分时,它会在结果中生成3 X 2 = 6条记录。副本起源于左侧的每条记录,右侧有2条记录。
这正是SQL应该表现的行为。