【问题标题】:"CASE" statement within "WHERE" clause in SQL Server 2008SQL Server 2008 中“WHERE”子句中的“CASE”语句
【发布时间】:2012-01-09 07:36:51
【问题描述】:

我正在处理一个在“WHERE”子句中包含“CASE”语句的查询。但是 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

【问题讨论】:

  • Case expression, not statement...(case 表达式返回一个值。case 语句用于存储过程中,用于有条件地执行代码。)

标签: sql sql-server case


【解决方案1】:

首先,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 

使用这样的组合 OR 语句可能会更好:

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

不过,无论哪种方式,我都不确定您会获得多棒的查询计划。 WHERE 子句中的这些类型的恶作剧通常会阻止查询优化器使用索引。

【讨论】:

  • WHEN 0 THEN co.personentered = co.personentered,这里不需要这个检查 co.personentered = co.personentered,因为它总是返回 true 并且长度值总是正的。因此,使 LEN('TestPerson') > 0 将减少需要比较的范围
  • 如何在选项 1 和 2 中检查 co.personentered 不为空。现在第 3 个选项就足够了。但我想知道……!!
  • 到目前为止我尝试过where case c when 1 then (DescriptionCode is null) else descriptioncode is not null end,但我显示的错误类似于Incorrect syntax near the keyword 'is'.
【解决方案2】:

尝试以下方法:

SELECT * FROM emp_master 
WHERE emp_last_name= 
CASE emp_first_name 
 WHEN 'test'    THEN 'test' 
 WHEN 'Mr name' THEN 'name'
END

【讨论】:

    【解决方案3】:

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

    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 
    

    【讨论】:

      【解决方案4】:

      我认为您的查询的开头应该是这样的:

      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 
      

      但是

      尾巴里的东西完全看不懂

      【讨论】:

        【解决方案5】:

        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 
        

        【讨论】:

          【解决方案6】:

          感谢这个问题,实际上我正在寻找以下查询中的其他内容。这可能对某人有所帮助。

                SELECT DISTINCT CASE WHEN OPPORTUNITY='' THEN '(BLANK)' ELSE OPPORTUNITY END
            AS OPP,LEN(OPPORTUNITY) FROM [DBO].[TBL]
          

          上面的查询是填写下拉列表,其中空白值显示为“(空白)”。此外,如果我们将此值传递给 sql where 子句以获取具有其他值的空白值,我不知道如何处理。最后提出了以下解决方案,这可能对某人有所帮助。

          来了,

           DECLARE @OPP TABLE (OPP VARCHAR(100))
            INSERT INTO @OPP VALUES('(BLANK)'),('UNFUNDED'),('FUNDED/NOT COMMITTED')
          SELECT DISTINCT [OPPORTUNITY]
          FROM [DBO].[TBL]   WHERE    (  CASE WHEN   OPPORTUNITY ='' THEN '(BLANK)' ELSE OPPORTUNITY END IN (SELECT OPP FROM @OPP))
          ORDER BY 1 
          

          【讨论】:

            【解决方案7】:
             select 
            d.DISTNAME,e.BLKNAME,a.childid,a.studyingclass 
            from Tbl_AdmissionRegister a
            inner join District_master b on a.Schooid=b.Schooid
            where 
            case when len('3601')=4   then c.distcd 
                       when len('3601')=6   then c.blkcd  
                       when len('3601')=11  then c.schcd   end = '3601'
            

            【讨论】:

            • 请提供更多信息,说明您的回答为何有助于解决原始问题。对于有同样问题的用户来说,只发布代码可能有点模糊。
            【解决方案8】:

            您也可以尝试如下所示。仅显示出境货件

               SELECT shp_awb_no,shpr_ctry_cd, recvr_ctry_cd,
                 CASE WHEN shpr_ctry_cd = record_ctry_cd 
                 THEN "O" 
                 ELSE "I" 
                  END AS route
                 FROM shipment_details
                WHERE record_ctry_cd = "JP"
                  AND "O" = CASE WHEN shpr_ctry_cd = record_ctry_cd 
                            THEN "O" 
                            ELSE "I" 
                             END
            

            【讨论】:

              【解决方案9】:

              这是我的解决方案

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

              问候 戴维

              【讨论】:

                【解决方案10】:

                这行得通

                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)
                

                【讨论】:

                  【解决方案11】:
                  CASE LEN('TestPerson')
                      WHEN 0 THEN co.personentered  = co.personentered ELSE co.personentered LIKE '%TestPerson'
                  

                  尝试以下方法:

                  ... and ( 
                      (LEN('TestPerson') = 0 and co.personentered  = co.personentered) or
                      (LEN('TestPerson') <> 0 and co.personentered LIKE '%TestPerson') ) and ...
                  

                  【讨论】:

                    【解决方案12】:
                    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')
                    

                    【讨论】:

                      【解决方案13】:
                      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';
                      

                      这样使用。

                      【讨论】:

                        猜你喜欢
                        • 2013-12-06
                        • 2021-08-09
                        • 1970-01-01
                        • 1970-01-01
                        • 2013-06-30
                        • 1970-01-01
                        • 1970-01-01
                        • 2020-03-26
                        相关资源
                        最近更新 更多