2012-01-09 16 views
73

Sto lavorando con una query che contiene l'istruzione "CASE" all'interno della clausola "WHERE". Ma SQL Server 2008 sta dando alcuni errori durante l'esecuzione. Qualcuno può aiutarmi con la query corretta? Ecco la domanda:Istruzione "CASE" all'interno della clausola "WHERE" in SQL Server 2008

SELECT 
    tl.storenum 'Store #', 
    co.ccnum 'FuelFirst Card #', 
    co.dtentered 'Date Entered', 
    CASE st.reasonid 
     WHEN 1 THEN 'Active' 
    WHEN 2 THEN 'Not Active' 
    WHEN 0 THEN st.ccstatustypename 
    ELSE 'Unknown' 
    END 'Status', 
    CASE st.ccstatustypename 
     WHEN 'Active' THEN ' ' 
    WHEN 'Not Active' THEN ' ' 
    ELSE st.ccstatustypename 
    END 'Reason', 
    UPPER(REPLACE(REPLACE(co.personentered,'RT\\\\',''),'RACETRAC\\\\','')) 'Person Entered', 
    co.comments 'Comments or Notes' 
FROM 
    comments co 
    INNER JOIN cards cc ON co.ccnum=cc.ccnum 
    INNER JOIN customerinfo ci ON cc.customerinfoid=ci.customerinfoid 
    INNER JOIN ccstatustype st ON st.ccstatustypeid=cc.ccstatustypeid 
    INNER JOIN customerstatus cs ON cs.customerstatuscd=ci.customerstatuscd 
    INNER JOIN transactionlog tl ON tl.transactionlogid=co.transactionlogid 
    LEFT JOIN stores s ON s.StoreNum = tl.StoreNum 
WHERE 
    CASE LEN('TestPerson') 
     WHEN 0 THEN co.personentered = co.personentered 
    ELSE co.personentered LIKE '%TestPerson' 
    END 
    AND cc.ccnum = CASE LEN('TestFFNum') 
     WHEN 0 THEN cc.ccnum 
    ELSE 'TestFFNum' 
    END 
    AND CASE LEN('2011-01-09 11:56:29.327') 
     WHEN 0 THEN co.DTEntered = co.DTEntered 
    ELSE 
     CASE LEN('2012-01-09 11:56:29.327') 
      WHEN 0 THEN co.DTEntered >= '2011-01-09 11:56:29.327' 
     ELSE co.DTEntered BETWEEN '2011-01-09 11:56:29.327' AND '2012-01-09 11:56:29.327' 
     END 
    END 
    AND tl.storenum < 699 
ORDER BY tl.StoreNum 

risposta

146

Prima di tutto, la dichiarazione deve essere CASEparte dell'espressione, non è l'espressione stessa.

In altre parole, si può avere:

WHERE co.DTEntered = CASE 
          WHEN LEN('blah') = 0 
           THEN co.DTEntered 
          ELSE '2011-01-01' 
        END 

Ma non funzionerà nel modo che hai scritto per esempio:

WHERE 
    CASE LEN('TestPerson') 
     WHEN 0 THEN co.personentered = co.personentered 
    ELSE co.personentered LIKE '%TestPerson' 
    END 

Si può avere più fortuna utilizzando istruzioni combinate o come this:

WHERE (
     (LEN('TestPerson') = 0 
      AND co.personentered = co.personentered 
     ) 
     OR 
     (LEN('TestPerson') <> 0 
      AND co.personentered LIKE '%TestPerson') 
    ) 

Anche se, in entrambi i casi, non sono sicuro di quanto grande possa essere un piano di query. Questi tipi di shenanigans in una clausola WHERE spesso impediscono a Query Optimizer di utilizzare gli indici.

+1

QUANDO 0 THEN co .p ersonentered = co.personentered, Qui questo controllo co.personentered = co.personentered non è necessario in quanto restituirà sempre true e il valore di lunghezza sarà sempre positivo. Quindi, fare LEN ('TestPerson')> 0 ridurrà l'intervallo necessario per essere confrontato – Satyajit

5

Penso che l'inizio della query dovrebbe essere simile che:

SELECT 
    tl.storenum [Store #], 
    co.ccnum [FuelFirst Card #], 
    co.dtentered [Date Entered], 
    CASE st.reasonid 
     WHEN 1 THEN 'Active' 
     WHEN 2 THEN 'Not Active' 
     WHEN 0 THEN st.ccstatustypename 
     ELSE 'Unknown' 
    END [Status], 
    CASE st.ccstatustypename 
     WHEN 'Active' THEN ' ' 
     WHEN 'Not Active' THEN ' ' 
     ELSE st.ccstatustypename 
     END [Reason], 
    UPPER(REPLACE(REPLACE(co.personentered,'RT\\\\',''),'RACETRAC\\\\','')) [Person Entered], 
    co.comments [Comments or Notes] 
FROM comments co 
    INNER JOIN cards cc ON co.ccnum=cc.ccnum 
    INNER JOIN customerinfo ci ON cc.customerinfoid=ci.customerinfoid 
    INNER JOIN ccstatustype st ON st.ccstatustypeid=cc.ccstatustypeid 
    INNER JOIN customerstatus cs ON cs.customerstatuscd=ci.customerstatuscd 
    INNER JOIN transactionlog tl ON tl.transactionlogid=co.transactionlogid 
    LEFT JOIN stores s ON s.StoreNum = tl.StoreNum 
WHERE 
    CASE 
     WHEN (LEN([TestPerson]) = 0 AND co.personentered = co.personentered) OR (LEN([TestPerson]) <> 0 AND co.personentered LIKE '%'+TestPerson) THEN 1 
     ELSE 0 
     END = 1 
    AND 

MA

ciò che è nella coda è completamente non comprensibile

12

Questo dovrebbe risolvere il problema per al momento ma devo ricordarti che non è un buon approccio:

WHERE 
      CASE LEN('TestPerson') 
       WHEN 0 THEN 
         CASE WHEN co.personentered = co.personentered THEN 1 ELSE 0 END 
       ELSE 
         CASE WHEN co.personentered LIKE '%TestPerson' THEN 1 ELSE 0 END 
      END = 1 
     AND cc.ccnum = CASE LEN('TestFFNum') 
          WHEN 0 THEN cc.ccnum 
          ELSE 'TestFFNum' 
         END 
     AND CASE LEN('2011-01-09 11:56:29.327') 
       WHEN 0 THEN CASE WHEN co.DTEntered = co.DTEntered THEN 1 ELSE 0 END 
       ELSE 
        CASE LEN('2012-01-09 11:56:29.327') 
         WHEN 0 THEN 
          CASE WHEN co.DTEntered >= '2011-01-09 11:56:29.327' THEN 1 ELSE 0 END 
         ELSE 
          CASE WHEN co.DTEntered BETWEEN '2011-01-09 11:56:29.327' 
                 AND '2012-01-09 11:56:29.327' 
                THEN 1 ELSE 0 END 
        END 
      END = 1 
     AND tl.storenum < 699 
-1
select TUM1.userid,TUM1.first_name + ' ' +TUM1.last_name as NAME,tum1.Business_Title,TUM1.manager_id,tum2.First_Name + ' ' + tum2.Last_Name as [MANAGER NAME],TUM1.project,TUM1.project_code,TUM1.rcc_code,TUM1.department,TCM.Company_Name, 
case 
when tum1.Gender_ID=1 then 'male' 
else 'female' 
end 'GENDER' 
,tum1.Band as BAND, 
case when tum1.Inactive=0 then 'STILL IN COMPANY' 
else 'LEFT COMPANY' 
end 'ACTIVE/INACTIVE' 
from tbl_user_master TUM1 
join tbl_Company_Master TCM on TCM.Company_Code=TUM1.Company_Code 
join tbl_User_Master TUM2 on TUM1.Manager_ID=TUM2.UserID 
where tum1.UserID in ('54545414') 
10

provare quanto segue:

select * From emp_master 
where emp_last_name= 
case emp_first_name 
when 'test' then 'test' 
when 'Mr name' then 'name' 
end 
-3
SELECT * from TABLE 
       WHERE 1 = CASE when TABLE.col = 100 then 1 
        when TABLE.col = 200 then 2 else 3 END 
        and TABLE.col2 = 'myname'; 

Usa in questo modo.

2

Ci WHERE parte potrebbe essere scritto in questo modo:

WHERE 
(LEN('TestPerson') <> 0 OR co.personentered = co.personentered) AND 
(LEN('TestPerson') = 0 OR co.personentered LIKE '%TestPerson') AND 
(cc.ccnum = CASE LEN('TestFFNum') 
       WHEN 0 THEN cc.ccnum 
       ELSE 'TestFFNum' 
       END) AND 
(LEN('2011-01-09 11:56:29.327') <> 0 OR co.DTEntered = co.DTEntered) AND 
((LEN('2011-01-09 11:56:29.327') = 0 AND LEN('2012-01-09 11:56:29.327') <> 0) OR co.DTEntered >= '2011-01-09 11:56:29.327' ) AND 
((LEN('2011-01-09 11:56:29.327') = 0 AND LEN('2012-01-09 11:56:29.327') = 0) OR co.DTEntered BETWEEN '2011-01-09 11:56:29.327' AND '2012-01-09 11:56:29.327' ) AND 
tl.storenum < 699 
0

qui è la mia soluzione

AND CLI.PE_NOM Like '%' + ISNULL(@NomClient, CLI.PE_NOM) + '%' 

Regads Davy

0

Questo funziona

declare @v int=A 
select * from Table_Name where XYZ=202 
and 
dbkey=(case @v when A then 'Some Value 1' 
else 'Some Value 2' 
end)