2014-09-16 84 views
5

ifadesinde nerede çalışıyorum üzerinde çalıştığım bir sorgu için where cümlede bir durum ifadesi yazmaya çalışıyorum. Kodu Crystal raporlarında içe aktarıyorum ve temelde, 'type' değişkeninin farklı bir tarih aralığı için başka bir yerde çalıştırılmakta olan bu tarih aralığı için 'create' çalıştırmaya ayarlı olup olmadığını söylemeye çalışıyorum. Bana bir hata veriyor. Sözdizimdeki neyin yanlış olduğunu belirleyemiyorum. Herkese yardım etsin mi?CASE deyimi, tqql sorgusunda

DECLARE @Date1 DATETIME 
DECLARE @Date2 DATETIME 
DECLARE @type VARCHAR(20) 
SET @Date1 = '2010-1-1' 
SET @Date2 = '2010-2-1' 
SET @type = '{?DateType}' 

select * 
from filled 
WHERE 
    (CASE WHEN @type = 'create' THEN 
    filled.CREATEDON >= @Date1 
    AND filled.CREATEDON < DATEADD(d, +1, @Date2) 
    WHEN @type <> 'create' THEN 
    filled.datefilled >= @Date1 
    AND filled.datefilled < DATEADD(d, +1, @Date2) 
    END) 
+0

Ne tür bir hata alıyorsunuz? Ve neden '@ type = 'create'' için 2 kontrolünüz var? – Andrew

+0

Ama sonra tüm SQL – aMazing

+0

olduğunda Crystal Report neden işaretlenmiş çünkü Sorgu kristal içine alma yapıyorum. – Barzul

cevap

12

Bir case deyimi

WHERE ((@type = 'create' and filled.CREATEDON >= @Date1 AND filled.CREATEDON < DATEADD(d, +1, @Date2)) or 
     (@type <> 'create' and filled.datefilled >= @Date1 AND filled.datefilled < DATEADD(d, +1, @Date2)) 
    ) 

Bu case açıklamada sahip olmayan sensical mantığı bırakır gerekmez. Her iki koşul da @type için aynı değere sahiptir. Bir yazım hatası olduğunu varsayalım. bir VAKA ifadeyi kullanarak

+0

Evet, aslında bir yazım hatası olması gerekiyordu <>. Teşekkürler. – Barzul

7

fıkra mümkündür, ancak genellikle önlenebilir ve AND/OR kullanılarak yeniden yazılması nerede, senin durumunda İÇİNDE olurdu: Böyle

WHERE( @Type = 'create' 
    AND filled.CREATEDON >= @Date1 
    AND filled.CREATEDON < DATEADD(d, +1, @Date2) 
    ) 
OR ( @Type != 'create' 
    AND filled.datefilled >= @Date1 
    AND filled.datefilled < DATEADD(d, +1, @Date2) 
    ) 

ANCAK sorguları genellikle optimal üretmek planları. Sen eğer mümkünse IF/ELSE mantığı kullanmalısınız:

IF @Type = 'create' 
BEGIN 
    SELECT * 
    FROM Filled 
    WHERE Filled.CreatedOn >= @Date1 
    AND  Filled.CreatedOn < DATEADD(DAY, 1, @Date2) 
END 
ELSE 
BEGIN 
    SELECT * 
    FROM Filled 
    WHERE Filled.DateFilled >= @Date1 
    AND  Filled.DateFilled < DATEADD(DAY, 1, @Date2) 
END 

Bunun nedeni @type değeri bu nedenle, DateFilled veya CreatedOn üzerinde aramanıza gerek olup olmayacağını bu nedenle optimizasyoncusu bilmez, derleme zamanında bilinen değil mi herhangi bir sütunda (varsa) bir dizin kullanmayı planlayamaz, bu nedenle mevcut dizinlerden bağımsız olarak bir tablo taraması yapar. Eğer mantığı IF/ELSE ile ayırırsanız, @type değerinin ne olduğu önemli değildir, IF'un her dalı için bir plan oluşturulur ve her dalda optimiser hangi sütunun aranacağını bilir ve kullanmayı planlayabilir. uygun dizin.

Ayrıca UNION ALL kullanabilirsiniz: endeksler DateFilled veya CreatedOn bulunuyorsa

SELECT * 
FROM Filled 
WHERE Filled.CreatedOn >= @Date1 
AND  Filled.CreatedOn < DATEADD(DAY, 1, @Date2) 
AND  @Type = 'create' 
UNION ALL 
SELECT * 
FROM Filled 
WHERE Filled.DateFilled >= @Date1 
AND  Filled.DateFilled < DATEADD(DAY, 1, @Date2) 
AND  @Type <> 'create'; 

Yine, bu OR kullanmaktan daha onları kullanan bir plan üretmek için çok daha muhtemeldir.