KHÔNG (a = 1 VÀ b = 1) so với (a <> 1 VÀ b <> 1)


16

Trong WHEREmệnh đề của truy vấn SQL, tôi mong muốn hai điều kiện này có cùng hành vi:

NOT (a=1 AND b=1)

đấu với

a<>1 AND b<>1

Điều kiện đầu tiên hoạt động như mong đợi, và trong khi tôi sử dụng điều kiện thứ hai để làm điều tương tự, thì không.

Đây là những thứ rất cơ bản, nhưng xấu hổ là tôi không thể thấy những gì tôi đang làm sai.


Bạn có thể đăng dữ liệu ví dụ và kết quả mong đợi so với kết quả thực tế không?
Gareth Lyons

6
Như Lenard đã lưu ý trong câu trả lời của mình, đây là một ví dụ về các quy tắc của De Morgan: không (A và B) = (không phải A) hoặc (không B) , không (A hoặc B) = (không phải A) và (không phải B) . Hãy cẩn thận với các giá trị NULL.
Barranka

2
Chỉ cần nghĩ về nó bằng tiếng Anh. Đầu tiên của bạn là "Không phải tôi là Vua của Pháp và cũng là con người" - hoàn toàn đúng. Thứ hai của bạn là "Tôi không phải là Vua của Pháp hay con người" - hoàn toàn sai.
Patrick Stevens

3
Điều này mâu thuẫn với "luật của De Morgan". Tương đương sẽ là a <> 1 OR b<>1.
Willem Van Onsem

Câu trả lời:


46

Chúng không tương đương.

NOT (a=1 AND b=1)

tương đương với:

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

Sự tương đương này được gọi là De Morgan's Law. Xem ví dụ:

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

Một kỹ thuật hay để chứng minh / từ chối các tương đương cho các biểu thức đại số boolean là sử dụng một cte cho các miền và so sánh các biểu thức cạnh nhau:

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

Chỉnh sửa: Vì DB2 không hỗ trợ kiểu dữ liệu Boolean, tôi đã mở rộng ví dụ tại:

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

Truy vấn viết lại trông giống như:

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;

Kết quả của truy vấn là:

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)

Như được hiển thị exp1 và exp2 là tương đương.


16
+1 chỉ để đề cập đến De Morgan. Nên đọc yêu cầu cho bất cứ ai làm bất kỳ hình thức lập trình / kịch bản.
Tonny

Nhưng còn NULL thì sao?
dan04

@ dan04 Bạn có thể thêm NULL vào dòng đầu tiên (trở thành with T(a) as ( values 0,1,NULL )và chạy lại truy vấn và bạn sẽ thấy điều gì xảy ra. NULL chắc chắn ném cờ lê trong hầu hết các quy tắc tương đương đã đặt mà chúng tôi tìm hiểu. Câu trả lời ngắn là a = NULL và < > NULL đều mang lại NULL, vì vậy chúng sẽ rơi vào trường hợp khác. Để đọc thêm: ( stackoverflow.com/questions/1833949/ trên )
Brian J

Tôi không chắc tại sao bạn phải sửa đổi ví dụ đầu tiên cho DB2. Nó hoạt động như hiển thị cho tôi. Tôi đang sử dụng DB2 cho i chứ không phải DB2 LUW. Ví dụ thứ hai có một số lỗi cú pháp cho DB2 cho i.
jmarkmurphy

@jmarkmurphy, tôi không biết DB2 cho tôi, có lẽ nó hoạt động ở đó. Đối với LUW, biểu thức trường hợp ánh xạ thành 0 hoặc 1 do đó phải được thay đổi để bao gồm cả null. Bằng cách làm như vậy, biểu thức trường hợp không còn tầm thường (IMO) và các biểu thức trở nên khó lý luận.
Lennart

9

Ví dụ đầu tiên của bạn là nói:

Trả về tất cả các hàng trừ trường hợp cả a = 1 b = 1

Ví dụ thứ hai của bạn là nói:

Return all rows trừ nơi hoặc một = 1 HOẶC b = 1

Để truy vấn thứ hai trả về giống như truy vấn đầu tiên, bạn nên thay đổi truy vấn của mình ANDthànhOR

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);

Điều này trả về kết quả sau

a   b
0   0
1   0
0   1

Bạn có thể mô tả lý do tại sao a<>1 AND b<>1dịch thành "a = 1 OR b = 1" không?
ngờ1ejack

1
@ myst1ejack, bạn cần một phủ định bổ sung trong câu lệnh thứ hai để làm cho nó tương đương với câu đầu tiên : NOT ( a=1 OR b=1 ). Ngôn ngữ tự nhiên không may có chứa sự mơ hồ gây khó khăn cho việc dịch các công thức logic sang ngôn ngữ tự nhiên và ngược lại. Ví dụ, có neither a=1 nor b=1nghĩa là NOT ( a=1 OR b=1 )hay (NOT a=1) OR (NOT b=1)?
Lennart

1
@ myst1ejack Ngược lại với "chiếc xe màu đỏ VÀ có bốn cửa" là "Hoặc chiếc xe không màu đỏ, HOẶC nó không có bốn cửa." Nếu nhiều điều phải đúng để đưa ra tuyên bố là đúng, thì chỉ một trong số đó phải sai để làm cho nó sai.
hobbs
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.