2012-01-09 140 views
73

我正在使用“WHERE”子句中包含“CASE”语句的查询。但是SQL Server 2008在执行时会出现一些错误。任何人都可以请帮助我正确的查询?下面是该查询:SQL Server 2008中“WHERE”子句中的“CASE”语句

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 

回答

146

首先,在CASE语句必须表达部分,不表达自己。

换句话说,你可以有:

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

但它不会工作,你已经写了他们的方式如:

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

您可以使用组合或之类的语句有更好的运气这个:

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

虽然,无论哪种方式,我不知道你会得到多好的查询计划。 WHERE子句中的这些形式通常会阻止查询优化器使用索引。

+1

WHEN 0 THEN合作.P ersonentered = co.personentered,在这里这个检查co.personentered = co.personentered是不需要的,因为它总是返回true,并且长度值总是正值。因此,使LEN('TestPerson')> 0将减少需要比较的范围 – Satyajit 2014-11-10 08:30:24

5

我认为您的查询的开头应该看起来像:

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 

什么是尾部完全无法理解

12

这应该解决您的问题的暂时但我必须提醒你,这不是一个好方法:

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

尝试以下方法:以这种方式

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

使用。

2

WHERE部分可以这样写:

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

这里是我的解决方案

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

Regads 戴维

0

这工作

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)