2008-11-17 18 views
30

Ben aptalca bir hata yapma eminim ama ne bilemiyorum: Daha önce bir çekince olanlar dışındaki tüm müşterileri seçme çalışıyorumSQL sorgusu soru: SEÇ ... DEĞİL İÇİNDE

SQL Server 2005'te 2:00 Bu sorguyu çalıştırdığınızda

:

SELECT idCustomer FROM reservations 
WHERE idCustomer NOT IN 
    (SELECT distinct idCustomer FROM reservations 
    WHERE DATEPART (hour, insertDate) < 2) 

Ben 0 sonuç almak.

Ama

SELECT idCustomer FROM reservations 

döner 152.000 sonuçları ve kısmen "DEĞİL İÇİNDE":

SELECT distinct idCustomer FROM reservations 
WHERE DATEPART (hour, insertDate) < 2 

döner sadece 284 satır

+0

Neden Farklı koyardı Senin içinde değil misin? 5 tanesi (1, 1, 2, 2, 3, 4, 4, 4, 4, 4)? Yinelenen varsa, umurumda değil. –

+1

Elbette, biraz çaresizleşiyor ve her şeyi deniyordum :) –

cevap

53
SELECT distinct idCustomer FROM reservations 
WHERE DATEPART (hour, insertDate) < 2 
    and idCustomer is not null 

Listenizi parametre null adlı içermediğinden emin olun değerler.

İşte açıklamaları aşağıda bulabilirsiniz:

WHERE field1 NOT IN (1, 2, 3, null) 

aynıdır: Geçen karşılaştırılması null değerlendirir

WHERE NOT (field1 = 1 OR field1 = 2 OR field1 = 3 OR field1 = null) 
  • O.
  • Buradaki boş değer, boole ifadesinin geri kalanı ile boş bırakılır. (*)
  • boş bırakılmış, boş bırakılır.
  • null doğru değil - yalnızca yan tümce tümce satırları tutuyor, bu nedenle tüm satırlar filtreleniyor.

(*) Düzenleme: bu açıklama oldukça iyi, ancak gelecekteki nitecemeyi durdurmak için bir şeyi ele almak istiyorum. (TRUE OR NULL) TRUE olarak değerlendirir. Bu, örneğin field1 = 3 ile ilgilidir. Bu TRUE değerinin FALSE olarak reddedileceği ve satırın filtreleneceği.

+0

O kadardı, teşekkürler! Hala nedenini anlamıyorum. Boş değerler null olanlar tarafından filtrelenmemelidir, değil mi? –

+0

Harika bir açıklama David, çok teşekkürler! –

2

SQL 2005, sen de bu bu Oracle'ın EKSİ komutuna benzer (BİRLİĞİ tersi)

deneyebilirsiniz Ama aynı zamanda ayıklama için DATEPART (saat, insertDate) sütun ekleyerek öneririm Verilen

SELECT idCustomer FROM reservations 
EXCEPT 
SELECT idCustomer FROM reservations WHERE DATEPART (hour, insertDate) < 2 
0
SELECT Reservations.idCustomer FROM Reservations (nolock) 
LEFT OUTER JOIN @reservations ExcludedReservations (nolock) ON Reservations.idCustomer=ExcludedReservations.idCustomer AND DATEPART(hour, ExcludedReservations.insertDate) < 2 
WHERE ExcludedReservations.idCustomer IS NULL AND Reservations.idCustomer IS NOT NULL 
GROUP BY Reservations.idCustomer 

[Güncelleme: idCustomer olmak NULL işlemek için ek ölçütler eklendi, görünüşe orijinal afişi vardı ana sorun oldu]

+0

Merhaba Kevin, problem customerId'nin null olması ve @David'in işaret ettiği gibi yine de çok teşekkürler! –

+0

Tamam. Sadece tamlık için ek kriterlere eklendi: -P Denemek için verilerim yok, fakat DIŞ JOIN'e karşı NOT IN'in EXECUTION planlarındaki farkı görmeyi merak ediyorum. Her neyse, sorununuzu çözdüğünüze sevindim. –

0

Maalesef bu noktayı kaçırdım, ama aşağıdakileri yapmak istediğin şeyi yapmaz mıyım?

SELECT distinct idCustomer FROM reservations 
WHERE DATEPART(hour, insertDate) >= 2 
+0

Ben de aynı şeyi düşünüyordum ... Ancak, bir müşteri iki rezervasyon, bir önce 2Am ve bir sonra, sizinkileri dahil edecektir ve onun olmaz. –

+0

Ah, bu mantıklı, beynim bugün tüm silindirleri ateşlemiyor! –

6

O IN listede NULL olması her zaman tehlikeli - genellikle ancak NOT IN için IN için beklendiği gibi davranır:

IF 1 NOT IN (1, 2, 3, NULL) PRINT '1 NOT IN (1, 2, 3, NULL)' 
IF 1 NOT IN (2, 3, NULL) PRINT '1 NOT IN (2, 3, NULL)' 
IF 1 NOT IN (2, 3) PRINT '1 NOT IN (2, 3)' -- Prints 
IF 1 IN (1, 2, 3, NULL) PRINT '1 IN (1, 2, 3, NULL)' -- Prints 
IF 1 IN (2, 3, NULL) PRINT '1 IN (2, 3, NULL)' 
IF 1 IN (2, 3) PRINT '1 IN (2, 3)' 
+0

İyi nokta. Bununla birlikte, liste içindeki boş değerlerin daha doğru bir yanıt vermesiyle asla karşılaşmadım. –

+0

Tam olarak - sorun, listenin dinamik olduğu ve NULL'un orada olduğunu bilmediğiniz ve bir IN aldığınız ve bir NOT IN olarak değiştirdiğinizdir. –

-1
SELECT MIN(A.maxsal) secondhigh 
FROM (
     SELECT TOP 2 MAX(EmployeeBasic) maxsal 
     FROM M_Salary 
     GROUP BY EmployeeBasic 
     ORDER BY EmployeeBasic DESC 
    ) A 
+3

SO'ya hoş geldiniz. Bu http://stackoverflow.com/help/how-to-answer adresini iyi yanıtlar nasıl oluşturacağınız konusunda okumak isteyebilirsiniz. Kod sadece cevaplar çok yardımcı olmaz, problemi nasıl çözdüğüne dair kısa bir açıklama ekleyebilirsiniz. – thebenman

-1
select * from table_name where id=5 and column_name not in ('sandy,'pandy'); 
+1

SO'ya hoş geldiniz. Bu stackoverflow.com/help/how-to-answer adresini iyi yanıtlar oluşturmak için okumak isteyebilirsiniz. Kod sadece cevaplar çok yararlı değildir, sorunun nasıl çözüldüğüne dair kısa bir açıklama ekleyebilirsiniz. – GhostCat