NOT (a = 1 AND b = 1) vs (a <> 1 AND b <> 1)


16

ในWHEREส่วนของแบบสอบถาม SQL ฉันคาดว่าสองเงื่อนไขนี้จะมีพฤติกรรมเหมือนกัน:

NOT (a=1 AND b=1)

VS

a<>1 AND b<>1

เงื่อนไขแรกทำงานตามที่คาดไว้และในขณะที่ฉัน epxect เงื่อนไขที่สองเพื่อทำสิ่งเดียวกันมันไม่ได้

นี่เป็นสิ่งพื้นฐานมาก แต่น่าละอายที่ฉันไม่เห็นสิ่งที่ฉันทำผิด


คุณสามารถโพสต์ข้อมูลตัวอย่างและผลลัพธ์ที่คาดหวังกับผลลัพธ์จริงได้หรือไม่
Gareth Lyons

6
เท่าที่สังเกตจาก Lenard ในคำตอบของเขานี้เป็นตัวอย่างของกฎ De มอร์แกนที่ใช้งาน: ไม่ได้ (A และ B) = (ไม่) หรือ (ไม่ B) , ไม่ได้ (A หรือ B) = (ไม่) และ (ไม่ B) . ระวังด้วยค่า NULL
Barranka

2
แค่คิดเป็นภาษาอังกฤษ สิ่งแรกของคุณคือ "ไม่ใช่กรณีที่ฉันเป็นทั้งราชาแห่งฝรั่งเศสและมนุษย์" - เด่นชัดอย่างแท้จริง ที่สองของคุณคือ "ฉันไม่ใช่ราชาแห่งฝรั่งเศสหรือมนุษย์" - เท็จอย่างเด่นชัด
Patrick Stevens

3
สิ่งนี้ขัดแย้งกับ "กฎหมายของเดอมอร์แกน" a <> 1 OR b<>1เทียบเท่าจะเป็น
Willem Van Onsem

คำตอบ:


46

พวกเขาจะไม่เทียบเท่า

NOT (a=1 AND b=1)

เทียบเท่ากับ:

(NOT a=1 OR NOT b=1) <=> (a<>1 OR b<>1)

De Morgan's Lawความเท่าเทียมกันนี้เรียกว่า ดูตัวอย่าง:

https://en.wikipedia.org/wiki/De_Morgan%27s_laws

เทคนิคที่ดีสำหรับการพิสูจน์ / หักล้างการเทียบเท่าสำหรับนิพจน์พีชคณิตแบบบูลคือใช้ cte สำหรับโดเมนและเปรียบเทียบนิพจน์เคียงข้างกัน:

with T(a) as ( values 0,1 )
   , U(a,b) as (select t1.a, t2.a as b 
               from t as t1 
               cross join t as t2
) 
select a,b
    , case when not (a=1 and b=1) then 1 else 0 end
    , case when a<>1 and b<>1 then 1 else 0 end 
from U

A           B           3           4          
----------- ----------- ----------- -----------
          0           0           1           1
          0           1           1           0
          1           0           1           0
          1           1           0           0

แก้ไข: เนื่องจาก DB2 ไม่สนับสนุนประเภทข้อมูล Boolean I จึงขยายตัวอย่างที่

http://sqlfiddle.com/#!15/25e1a/19

คิวรีที่เขียนซ้ำดูเหมือนว่า:

with T(a) as ( values (0),(1),(null) )
   , U(a,b) as (select t1.a, t2.a as b 
                from t as t1 
                cross join t as t2
) 
select a,b
     , not (a=1 and b=1) as exp1 
     , a<>1 or b<>1 as exp2
from U;

ผลลัพธ์ของแบบสอบถามคือ:

a       b       exp1        exp2
--------------------------------
0       0       true        true
0       1       true        true
0       (null)  true        true
1       0       true        true
1       1       false       false
1       (null)  (null)      (null)
(null)  0       true        true
(null)  1       (null)      (null)
(null)  (null)  (null)      (null)

ตามที่แสดง exp1 และ exp2 เทียบเท่า


16
+1 เพียงเพื่อกล่าวถึง De Morgan ควรจะต้องอ่านสำหรับทุกคนที่ทำรูปแบบของการเขียนโปรแกรม / สคริปต์
Tonny

แต่แล้ว NULL ล่ะ
dan04

@ dan04 คุณสามารถเพิ่ม NULL ในบรรทัดแรก (กลายเป็นwith T(a) as ( values 0,1,NULL )และเรียกใช้แบบสอบถามอีกครั้งและคุณจะเห็นสิ่งที่เกิดขึ้น NULL จะโยนประแจในกฎการเทียบเคียงที่เราเรียนรู้ส่วนใหญ่คำตอบสั้น ๆ คือ = NULL และ < > NULL ทั้งคู่ให้ผล NULL ดังนั้นพวกเขาจะตกไปที่กรณีอื่นสำหรับการอ่านเพิ่มเติม: ( stackoverflow.com/questions/1833949/… )
Brian J

ฉันไม่แน่ใจว่าทำไมคุณต้องแก้ไขตัวอย่างแรกสำหรับ DB2 มันทำงานตามที่ปรากฏสำหรับฉัน ฉันใช้ DB2 for i แทนที่จะเป็น DB2 LUW ตัวอย่างที่สองมีข้อผิดพลาดทางไวยากรณ์สำหรับ DB2 for i
jmarkmurphy

@jmarkmurphy ฉันไม่รู้ DB2 for i บางทีมันอาจใช้งานได้ สำหรับ LUW นิพจน์เคสจะจับคู่กับ 0 หรือ 1 ดังนั้นจะต้องเปลี่ยนเป็น null ด้วยเช่นกัน การทำเช่นนั้นนิพจน์กรณีจะไม่สำคัญอีกต่อไป (IMO) และการแสดงออกกลายเป็นเรื่องยากที่จะให้เหตุผล
Lennart

9

ตัวอย่างแรกของคุณกำลังพูดว่า:

ส่งคืนแถวทั้งหมดยกเว้นเมื่อทั้ง a = 1 AND b = 1

ตัวอย่างที่สองของคุณกำลังพูดว่า:

กลับแถวทั้งหมดยกเว้นที่ทั้ง A = 1 หรือข = 1

เพื่อให้แบบสอบถามที่สองกลับมาเหมือนเดิมคุณควรเปลี่ยนANDเป็นOR

CREATE TABLE #Test (a BIT, b BIT);

INSERT INTO #Test
        ( a, b )
VALUES
        ( 0, 0 ),
        ( 1, 0 ),
        ( 0, 1 ),
        ( 1, 1 );

SELECT * FROM #Test AS t
WHERE NOT (a=1 AND b=1);

SELECT * FROM #Test AS t
WHERE (a <> 1 OR b <> 1);

ส่งคืนผลลัพธ์ต่อไปนี้

a   b
0   0
1   0
0   1

คุณช่วยอธิบายได้ไหมว่าเหตุใดจึงa<>1 AND b<>1แปลเป็น "a = 1 หรือ b = 1"
doub1ejack

1
@ doub1ejack คุณต้องมีการปฏิเสธเพิ่มเติมในคำสั่งที่สองเพื่อให้เทียบเท่ากับคำสั่งแรก: NOT ( a=1 OR b=1 ). ภาษาธรรมชาติที่โชคร้ายมีความคลุมเครือซึ่งทำให้ยากที่จะแปลสูตรทางตรรกะเป็นภาษาธรรมชาติและในทางกลับกัน ตัวอย่างเช่นneither a=1 nor b=1หมายความว่าNOT ( a=1 OR b=1 )หรือ(NOT a=1) OR (NOT b=1)?
Lennart

1
@ doub1ejack ตรงกันข้ามกับ "รถเป็นสีแดงและมีสี่ประตู" คือ "ไม่ว่ารถจะไม่เป็นสีแดงหรือไม่มีสี่ประตู" หากมีหลายสิ่งที่จะต้องเป็นจริงที่จะทำให้คำสั่งจริงแล้วมีเพียงหนึ่งในนั้นจะต้องเป็นเท็จเพื่อให้เป็นเท็จ
ฮอบส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.