DEĞİL (a = 1 VE b = 1) vs (a <> 1 VE b <> 1)


16

Gelen WHERESQL sorgusunun maddesi aynı davranışa sahip bu iki koşulu beklenir:

NOT (a=1 AND b=1)

vs

a<>1 AND b<>1

İlk koşul beklendiği gibi davranır ve aynı şeyi yapmak için ikinci koşulu epksekteyken yapmaz.

Bu çok basit şeyler, ama utanarak neyi yanlış yaptığımı göremiyorum.


Örnek veriler ve beklenen sonuçları gerçek sonuçlara göre gönderebilir misiniz?
Gareth Lyons

6
Lenard'ın cevabında belirttiği gibi, bu De Morgan kurallarına bir örnektir: (A ve B) = (A değil) veya (B değil) , (A veya B) = (A değil) ve (B değil) . NULL değerlerine dikkat edin.
Barranka

2
Sadece İngilizce olarak düşünün. İlki "Hem Fransa Kralı hem de insan olduğum durum değil" - kesinlikle doğru. İkincisiniz "Ben ne Fransa Kralı ne de insanım" - kesinlikle yanlış.
Patrick Stevens

3
Bu, "De Morgan yasası" ile çelişiyor. Eşdeğer olacaktır a <> 1 OR b<>1.
Willem Van Onsem

Yanıtlar:


46

Eşdeğer değiller.

NOT (a=1 AND b=1)

şuna eşittir:

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

Bu denklik olarak bilinir De Morgan's Law. Örneğin bakınız:

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

Boole cebri ifadeleri için denklikleri kanıtlamak / reddetmek için güzel bir teknik, alanlar için bir cte kullanmak ve ifadeleri yan yana karşılaştırmaktır:

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

Düzenleme: DB2 Boole veri tipini desteklemediğinden ben de şu örneği genişlettim:

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

Yeniden yazılan sorgu şuna benzer:

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;

Sorgunun sonucu:

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)

Gösterildiği gibi exp1 ve exp2 eşdeğerdir.


16
+1 yalnızca De Morgan'dan bahsettiğin için. Herhangi bir programlama / komut dosyası yapan herkesin okuması gerekir.
Tonny

Peki ya NULL?
dan04

@ dan04 İlk satıra NULL ekleyebilirsiniz (olur with T(a) as ( values 0,1,NULL )ve sorguyu yeniden çalıştırın ve ne olduğunu göreceksiniz. NULL'lar, öğrendiğimiz ayarlanmış eşdeğerlik kurallarının çoğuna kesinlikle bir anahtar atarlar. Kısa cevap a = NULL ve < > NULL her ikisi de NULL verir, bu yüzden başka bir duruma düşerler.Daha fazla okuma için: ( stackoverflow.com/questions/1833949/… )
Brian J

DB2 için ilk örneği neden değiştirmek zorunda olduğunuzdan emin değilim. Benim için gösterildiği gibi çalışıyor. DB2 LUW yerine i için DB2 kullanıyorum. İkinci örnekte DB2 for i için bazı sözdizimi hataları var.
jmarkmurphy

@jmarkmurphy, i için DB2 bilmiyorum, belki orada çalışır. LUW için büyük / küçük harf ifadesi, 0 veya 1 ile eşleşir, böylece boş değeri de içerecek şekilde değiştirilmesi gerekir. Böyle yaparak vaka ifadesi artık önemsiz değildir (IMO) ve ifadelerin akıl yürütmesi zorlaşmaktadır.
Lennart

9

İlk örneğiniz diyor ki:

Tüm satırları iade haricinde nerede hem a = 1 VE b = 1

İkinci örneğiniz şöyle diyor:

Tüm satırları iade haricinde nerede ya bir 1 = VEYA b = 1

İkinci sorgunun birinciyle aynı olması ANDiçin,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);

Bu, aşağıdaki sonuçları döndürür

a   b
0   0
1   0
0   1

Neden a<>1 AND b<>1"ya a = 1 VEYA b = 1" e çevrildiğini açıklayabilir misiniz ?
doub1ejack

1
@ doub1ejack, ilk ile eşdeğer şekilde ikinci açıklamada ek bir olumsuzlamasıydı gerekir: NOT ( a=1 OR b=1 ). Talihsiz doğal diller, mantıksal formülleri doğal dillere çevirmeyi zorlaştıran belirsizlikler içerir veya bunun tersi de geçerlidir. Örneğin, mu neither a=1 nor b=1demek NOT ( a=1 OR b=1 )ya (NOT a=1) OR (NOT b=1)?
Lennart

1
@ doub1ejack "Arabanın kırmızısı VE dört kapısı var" ifadesinin tersi "Arabanın kırmızısı olmadığı VEYA dört kapısı olmadığı" şeklindedir. Bir ifadeyi doğru yapmak için birden fazla şeyin doğru olması gerekiyorsa, yanlış yapmak için bunlardan sadece birinin yanlış olması gerekir.
Ocaklar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.