Câu lệnh "CASE" trong mệnh đề "WHERE" trong SQL Server 2008


107

Tôi đang làm việc với một truy vấn có chứa câu lệnh "CASE" trong mệnh đề "WHERE". Nhưng SQL Server 2008 đang đưa ra một số lỗi khi thực thi nó. Bất cứ ai có thể vui lòng giúp tôi với câu hỏi chính xác? Đây là truy vấn:

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
Trường hợp biểu hiện , chứ không phải tuyên bố ... (Khái niệm trường hợp trả về một giá trị Những tuyên bố trường hợp được sử dụng trong thủ tục lưu trữ để thực hiện điều kiện của mã..)
jarlh

Câu trả lời:


204

Trước hết, CASEcâu lệnh phải là một phần của biểu thức, không phải chính biểu thức.

Nói cách khác, bạn có thể có:

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

Nhưng nó sẽ không hoạt động theo cách bạn đã viết, ví dụ:

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

Bạn có thể gặp may mắn hơn khi sử dụng các câu lệnh HOẶC kết hợp như sau:

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

Mặc dù, theo cách nào đó, tôi không chắc bạn sẽ nhận được kế hoạch truy vấn tuyệt vời như thế nào. Những kiểu tai quái này trong một WHEREmệnh đề thường sẽ ngăn trình tối ưu hóa truy vấn sử dụng các chỉ mục.


1
KHI 0 THÌ co.personentered = co.personentered, ở đây không cần kiểm tra này co.personentered = co.personentered vì nó sẽ luôn trả về true và giá trị độ dài sẽ luôn dương. Vì vậy, việc đặt LEN ('TestPerson')> 0 sẽ làm giảm phạm vi cần được so sánh
Satyajit

cách kiểm tra co.personenteredkhông phải là null, trong tùy chọn 1 và 2. Bây giờ tùy chọn thứ 3 là đủ. Nhưng tôi muốn biết rằng ... !!
Pugal

Tôi đã thử cho đến nay where case c when 1 then (DescriptionCode is null) else descriptioncode is not null end, nhưng tôi hiển thị lỗi nhưIncorrect syntax near the keyword 'is'.
Pugal

15

Điều này sẽ giải quyết được vấn đề của bạn trong lúc này nhưng tôi phải nhắc bạn rằng đó không phải là một cách tiếp cận tốt:

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 

12

Hãy thử những cách sau:

select * From emp_master 
where emp_last_name= 
case emp_first_name 
 when 'test'    then 'test' 
 when 'Mr name' then 'name'
end

6

Tôi nghĩ rằng phần đầu của truy vấn của bạn sẽ giống như sau:

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 

NHƯNG

những gì ở đuôi là hoàn toàn không hiểu


4

WHEREthể viết một phần như thế này:

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

Bạn cũng có thể thử như dưới đây, ví dụ: để chỉ hiển thị các Lô hàng đi

   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

Cảm ơn vì câu hỏi này, thực sự tôi đang tìm kiếm một thứ khác trong truy vấn bên dưới. điều này có thể giúp ai đó.

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

truy vấn trên là điền vào danh sách thả xuống mà các giá trị trống hiển thị là "(trống)". Ngoài ra nếu chúng tôi chuyển giá trị này vào mệnh đề sql where để nhận các giá trị trống với các giá trị khác, tôi không biết làm thế nào để xử lý điều đó. Và cuối cùng đã đưa ra giải pháp dưới đây, điều này có thể giúp ích cho ai đó.

nó đây,

 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

đây là giải pháp của tôi

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

Rất tiếc Davy


0

Những công việc này

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)

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

Hãy thử những cách sau:

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

Sử dụng theo cách này.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.