2012-01-09 11 views
73

Estoy trabajando con una consulta que contiene la instrucción "CASE" dentro de la cláusula "WHERE". Pero SQL Server 2008 está dando algunos errores al ejecutarlo. ¿Puede alguien ayudarme con la consulta correcta? Ésta es la consulta:instrucción "CASE" dentro de la cláusula "WHERE" en 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 

Respuesta

146

En primer lugar, la declaración debe ser CASE parte de la expresión, no la propia expresión.

En otras palabras, se puede tener:

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

pero no va a trabajar de la forma que ha escrito, por ejemplo:

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

Es posible que tenga mejor suerte usando declaraciones combinada o como esto:

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

Aunque, de cualquier manera, no estoy seguro de cuán grande de un plan de consulta obtendrá. Este tipo de engaños en una cláusula WHERE a menudo evitará que el optimizador de consultas utilice índices.

+1

CUANDO 0 ENTONCES co .pag ersonentered = co.personentered, Aquí este check co.personentered = co.person entrañado no es necesario ya que siempre devolverá true y el valor de la longitud siempre será positivo. Entonces, hacer LEN ('TestPerson')> 0 reducirá el rango necesario para ser comparado – Satyajit

5

creo que el inicio de la consulta debe ser similar a lo siguiente:

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 

PERO

lo que está en la cola es completamente incomprensible

12

Esto debería resolver su problema para el momento, pero debo recordarle que no es un buen enfoque:

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

intente lo siguiente:

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

Uso de esta manera.

2

Hay WHERE parte podría escribirse así:

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

aquí es mi solución

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

Regads Davy

0

Esto funciona

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) 
Cuestiones relacionadas