WHERE条件与NULL无关,消除了具有NULL值的行

时间:2017-04-04 04:52:05

标签: mysql join

CREATE TABLE players (
  `userID` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
PRIMARY KEY (`userID`));

CREATE TABLE opponents (
  `userID` INT NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(45) NOT NULL,
PRIMARY KEY (`userID`));

CREATE TABLE relationship (
  `user1_userID` INT NOT NULL,
  `user2_userID` INT NOT NULL,
  `blocked` TINYINT(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`user1_userID`, `user2_userID`));

INSERT INTO players (`name`) 
VALUES ('alpha'), ('beta'), ('gamma'), ('delta');

INSERT INTO opponents (`name`) 
VALUES ('alpha'), ('beta');

INSERT INTO relationship (`user1_userID`, `user2_userID`, `blocked`)
VALUES (1,2, 1), (1,3, 1), (1,4, 1), (2, 1, 1), (2,3, 1), (3,4, 1);

SELECT o.userID, o.name, ur.*
FROM opponents o
LEFT JOIN players p
    ON (o.userID != p.userID)
LEFT JOIN relationship ur
    ON ((ur.user1_userID = p.userID AND ur.user2_userID = o.userID) OR 
       (ur.user1_userID = o.userID AND ur.user2_userID = p.userID)) 
-- WHERE (ur.blocked != 1)

如果我没有提出WHERE条件,我会看到关系列的NULL行,即测试版未阻止delta。

但是当我取消注释WHERE条件时,我只希望保留此行。但它也被淘汰了。为什么会发生这种情况以及如何正确编写查询?感谢。

1 个答案:

答案 0 :(得分:0)

在SQL中,与某些编程语言不同,在某些编程语言中,您可以使用相等的(=)elvaluator来测试NULL,在ANSI SQL中,您不能也必须IS NULL或相反IS NOT NULL评估空值。这意味着,如果您使用=评估并且行具有NULL值,则它甚至不会被考虑,至少MySQL InnoDB就是这种情况,有些{{1}处理它们略有不同。

现在针对您的具体情况,您可以改变您的查询,以获得所需的结果

RMBDS

<强>已更新

因为我猜有时候我不是最好的解释者,而且最终我在互联网上的某些人是一些指向mysql文档的链接,这些链接应该有助于清理一些事情。希望帮助回答&#34;真正的问题&#34;

Comparison Functions and Oporators

Working With NULL VALUES

Problems With NULL

修改

我想更好地解释一下我的自我,值SELECT o.userID, o.name, ur.* FROM opponents o LEFT JOIN players p ON (o.userID != p.userID) LEFT JOIN relationship ur ON ((ur.user1_userID = p.userID AND ur.user2_userID = o.userID) OR (ur.user1_userID = o.userID AND ur.user2_userID = p.userID)) WHERE (ur.blocked != 1 OR ur.blocked IS NULL) 无法通过布尔运算符进行评估,因为NULL缺少值,并且因为它没有值,所以它既不能是1也不能是1因此,在任何布尔评估中,它永远不会返回false,例如NULLNULL=1都是假的。现在我还想提一下可能的替代解决方案,因为在数据库中正确处理空值非常重要,如果您想从数据库中获取准确的信息。

NULL!=1中的

除了MySQL之外,您还可以使用2个函数来提供所需的结果。

!=

COALESCE(ur.blocked,0) != 1 可以被赋予许多值,并将从左侧开始返回第一个非NULL值并进行右侧评估。因此,在您的情况下,将COALESCE(value, ...)评估为NULL,该0不等于1,并会返回您遗失的记录。

IFNULL(ur.blocked,0) != 1

IFNULL(Value1, Value2)如果第一个值不是NULL,此函数将返回第一个值,如果第一个值为NULL,则返回第二个值

希望这有助于您将来处理NULL值。