2017-04-04 37 views
0
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一行。WHERE條件不相關的NULL,消除了空行的值

但是,當我取消註釋WHERE條件,我期待只留下這一行。但它也被消除了。爲什麼會發生這種情況,以及如何正確編寫查詢?謝謝。

+0

將where子句更改爲WHERE ur.blocked IS NULL –

+0

使用(ur.blocked IS NULL)將是臨時解決方法。假設結果中有另一行,它的(ur.blocked是0)。我們希望所有具有NULL或0的行(基本上!= 1)。真正的問題是爲什麼(ur.blocked!= 1)消除了ur.blocked爲NULL的行? –

+0

它是NULL的原因是因爲在連接中沒有匹配的行。使用WHERE ur.blocked IS NULL或者ur.blocked <> 1. –

回答

0

在SQL不像一些編程語言,你可以使用相等(=)elvaluator來測試NULL,在ANSI SQL你不能,必須IS NULL或相反IS NOT NULL爲空值評估。這意味着如果您使用=評估和一行有NULL價值它甚至不會考慮,至少這是MySQL InnoDB的情況下,一些RMBDS處理它們稍有不同。

現在爲您的特定情況下,你可以改變你這樣的查詢,以獲得期望的結果

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) 

修訂

becaue我想有時候我不是最好的解釋器,並在年底當天我只是一些在互聯網上的人,這裏有一些鏈接到mysql文檔,應該有助於澄清一些事情。希望幫助回答 「真正的問題」

Comparison Functions and Oporators

Working With NULL VALUES

Problems With NULL

編輯

我想解釋我自己好,價值NULL無法通過評估一個布爾運算符,因爲NULL是沒有值的,因爲它有沒有值它不能是1也不是0,所以在任何布爾評估中它都不會返回false,例如NULL=1NULL!=1都是假的。現在我還想提及可能的替代解決方案,因爲在數據庫中正確處理空值對於您想從數據庫獲取準確信息非常重要。

in MySQL除了!=之外,還有兩個功能可以使用,它們會給你想要的結果。

COALESCE(ur.blocked,0) != 1 

COALESCE(value, ...)可以給出許多值,並返回從左和評估右邊開始的第一個非NULL值。所以在你的情況下,將評估NULL0,這不會等於1,並會返回您的缺失記錄。

​​

IFNULL(Value1, Value2)這個函數將返回第一個如果不是NULL,如果第一個值是NULL

希望這將有助於你在未來處理NULL值返回第二個值。

+0

真正的問題是爲什麼(ur.blocked!= 1)消除了ur.blocked爲NULL的行?你的答案說明爲什麼(ur.blocked = NULL)在MySQL中不起作用 –

+0

我想總結一下當我試圖在mysql InnoDB中說出什麼時候有一個空值的字段,並且該字段是基於where子句中的'='評估程序來限制,它將刪除所有那些字段爲空的記錄,因爲它不能用'='或本例中的'!=' – Jpsh