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
条件时,我只希望保留此行。但它也被淘汰了。为什么会发生这种情况以及如何正确编写查询?感谢。
答案 0 :(得分:0)
在SQL中,与某些编程语言不同,在某些编程语言中,您可以使用相等的(=
)elvaluator来测试NULL
,在ANSI SQL
中,您不能也必须IS NULL
或相反IS NOT NULL
评估空值。这意味着,如果您使用=
评估并且行具有NULL
值,则它甚至不会被考虑,至少MySQL InnoDB
就是这种情况,有些{{1}处理它们略有不同。
现在针对您的具体情况,您可以改变您的查询,以获得所需的结果
RMBDS
<强>已更新强>
因为我猜有时候我不是最好的解释者,而且最终我在互联网上的某些人是一些指向mysql文档的链接,这些链接应该有助于清理一些事情。希望帮助回答&#34;真正的问题&#34;
Comparison Functions and Oporators
修改强>
我想更好地解释一下我的自我,值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,例如NULL
和NULL=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
值。