คำสั่ง“ CASE” ภายในส่วนคำสั่ง“ WHERE” ใน SQL Server 2008


108

ฉันกำลังทำงานกับข้อความค้นหาที่มีคำสั่ง "CASE" ภายในอนุประโยค "WHERE" แต่ 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

2
นิพจน์เคสไม่ใช่คำสั่ง ... (นิพจน์เคสส่งคืนค่าคำสั่งเคสถูกใช้ในโพรซีเดอร์ที่เก็บไว้สำหรับการเรียกใช้โค้ดแบบมีเงื่อนไข)
jarlh

คำตอบ:


207

ก่อนอื่น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')
      )

แม้ว่าฉันจะไม่แน่ใจว่าคุณจะได้รับแผนการสืบค้นข้อมูลที่ยอดเยี่ยมเพียงใด ประเภทของ shenanigans เหล่านี้ในWHEREประโยคมักจะป้องกันไม่ให้เครื่องมือเพิ่มประสิทธิภาพการสืบค้นใช้ดัชนี


1
เมื่อ 0 แล้ว co.personentered = co.personentered ในที่นี้ไม่จำเป็นต้องตรวจสอบ co.personentered = co.personentered เนื่องจากจะส่งคืนค่าจริงเสมอและค่าความยาวจะเป็นบวกเสมอ ดังนั้นการทำให้ LEN ('TestPerson')> 0 จะช่วยลดช่วงที่ต้องการเปรียบเทียบ
Satyajit

วิธีการตรวจสอบco.personenteredไม่เป็นโมฆะในตัวเลือก 1 และ 2 ตอนนี้ตัวเลือก 3 rd ก็เพียงพอแล้ว แต่อยากรู้ว่า ... !!
Pugal

ฉันพยายามwhere case c when 1 then (DescriptionCode is null) else descriptioncode is not null endแล้ว แต่ฉันแสดงข้อผิดพลาดเช่นIncorrect syntax near the keyword 'is'.
Pugal

15

วิธีนี้ควรแก้ปัญหาของคุณในขณะนี้ แต่ฉันต้องเตือนคุณว่าไม่ใช่แนวทางที่ดี:

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 


6

ฉันคิดว่าจุดเริ่มต้นของข้อความค้นหาของคุณควรมีลักษณะดังนี้:

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 

แต่

สิ่งที่อยู่ในหางนั้นไม่สามารถเข้าใจได้อย่างสมบูรณ์


4

มี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 

1

คุณสามารถลองเช่นด้านล่างเช่น เพื่อแสดงเฉพาะการจัดส่งขาออก

   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

1

ขอบคุณสำหรับคำถามนี้จริงๆแล้วฉันกำลังมองหาอย่างอื่นซึ่งอยู่ในแบบสอบถามด้านล่าง สิ่งนี้อาจช่วยใครบางคนได้

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

ข้อความค้นหาด้านบนคือการกรอกข้อมูลในรายการแบบเลื่อนลงซึ่งค่าว่างจะแสดงเป็น "(ว่าง)" นอกจากนี้ถ้าเราส่งค่านี้ไปยัง sql โดยที่ clause เพื่อรับค่าว่างด้วยค่าอื่นฉันไม่รู้ว่าจะจัดการอย่างไร และในที่สุดก็มีวิธีแก้ปัญหาด้านล่างซึ่งอาจช่วยให้ใครบางคนได้

นี่คือ

 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 



0
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 ...

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

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

ใช้ในลักษณะนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.