在右侧元素上使用AND了解左外连接,仍然导致重复条目(使用sql小提琴)

时间:2014-11-26 09:44:40

标签: mysql sql join sqlfiddle

我的问题是:我的想法出现了什么问题?

为什么左连接不按我想象的那样工作?

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。

为什么不呢?

1 个答案:

答案 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应该表现的行为。