2008-10-15 28 views
127

Tôi đã thử tìm kiếm xung quanh nhưng không thể tìm thấy bất kỳ thứ gì có thể giúp tôi.Chuyển đổi/Trường hợp SQL trong mệnh đề

Tôi đang cố gắng để làm điều này trong SQL:

declare @locationType varchar(50); 
declare @locationID int; 

SELECT column1, column2 
FROM viewWhatever 
WHERE 
CASE @locationType 
    WHEN 'location' THEN account_location = @locationID 
    WHEN 'area' THEN xxx_location_area = @locationID 
    WHEN 'division' THEN xxx_location_division = @locationID 

tôi biết rằng tôi không cần phải đặt '= @locationID' ở phần cuối của mỗi người nhưng tôi không thể có được cú pháp thậm chí gần đúng. SQL tiếp tục phàn nàn về '=' của tôi trên dòng WHEN đầu tiên ...

Trợ giúp!

Trả lời

165
declare @locationType varchar(50); 
declare @locationID int; 

SELECT column1, column2 
FROM viewWhatever 
WHERE 
@locationID = 
    CASE @locationType 
     WHEN 'location' THEN account_location 
     WHEN 'area' THEN xxx_location_area 
     WHEN 'division' THEN xxx_location_division 
    END 
+1

Như TomH lưu ý trong những nhận xét trả lời của bạn dưới đây, bạn đã thành lập SQL không chính xác. Tôi đã thử nghiệm của tôi trong SQLServer 2005 và nó hoạt động tốt. –

+0

Tại sao cần @? Họ làm gì? – JedatKinports

6

Tôi muốn nói đây là chỉ báo về cấu trúc bảng thiếu sót. Có lẽ các loại vị trí khác nhau nên được phân tách trong các bảng khác nhau, cho phép bạn thực hiện nhiều truy vấn phong phú hơn và tránh việc có các cột không cần thiết xung quanh.

Nếu bạn không thể thay đổi cấu trúc, giống như dưới đây có thể làm việc:

SELECT 
    * 
FROM 
    Test 
WHERE 
    Account_Location = (
     CASE LocationType 
      WHEN 'location' THEN @locationID 
      ELSE Account_Location 
     END 
    ) 
    AND 
    Account_Location_Area = (
     CASE LocationType 
      WHEN 'area' THEN @locationID 
      ELSE Account_Location_Area 
     END 
    ) 

Và vân vân ... Chúng ta không thể thay đổi cấu trúc của các truy vấn một cách nhanh chóng, nhưng chúng tôi có thể ghi đè nó bằng cách làm cho các vị từ bằng nhau.

CHỈNH SỬA: Các đề xuất ở trên tất nhiên tốt hơn nhiều, chỉ cần bỏ qua mỏ của tôi.

+0

Tôi không nghĩ đây là cấu trúc bảng thiếu sót.Bảng đã được thiết lập theo cách này để nó tự tham chiếu để có một số lượng vô hạn quan hệ cha/con. Tin tôi đi, đó là mục đích. Tôi không nghĩ rằng tôi muốn thay đổi cấu trúc bảng của tôi để chỉ sử dụng một tuyên bố chuyển đổi. nĐể của nó mà quan trọng – Miles

4

Vấn đề với điều này là khi công cụ SQL đi để đánh giá biểu thức, nó kiểm tra phần TỪ để kéo các bảng thích hợp và sau đó là phần WHERE để cung cấp một số tiêu chí cơ sở, vì vậy nó không thể đánh giá đúng điều kiện động trên cột nào cần kiểm tra.

Bạn có thể sử dụng một mệnh đề WHERE khi bạn đang kiểm tra các tiêu chí WHERE trong vị ngữ, chẳng hạn như

WHERE account_location = CASE @locationType 
           WHEN 'business' THEN 45 
           WHEN 'area' THEN 52 
         END 

như vậy trong trường hợp cụ thể của bạn, bạn sẽ cần phải đặt truy vấn vào một thủ tục lưu trữ hoặc tạo ba truy vấn riêng biệt.

28

Thông tin cho bạn đây.

SELECT 
    column1, 
    column2 
FROM 
    viewWhatever 
WHERE 
CASE 
    WHEN @locationType = 'location' AND account_location = @locationID THEN 1 
    WHEN @locationType = 'area' AND xxx_location_area = @locationID THEN 1 
    WHEN @locationType = 'division' AND xxx_location_division = @locationID THEN 1 
    ELSE 0 
END = 1 
+5

Vâng, tôi đã có viết rằng như CHỌN column1, column2 TỪ viewWhatever ĐÂU (@locationType = 'vị trí' VÀ account_location = @locationID) OR (@locationType = 'khu vực' VÀ xxx_location_area = @locationID) HOẶC (@locationType = 'division' AND xxx_location_division = @locationID) –

+2

đây là một ví dụ tuyệt vời về cách thực thi truy vấn với trả lời tốt nhất (cá nhân tôi thích mã phương thức này rõ ràng và rõ ràng) – PEO

+1

thực sự tuyệt vời nếu bạn muốn sử dụng mệnh đề where khác nhau với các kiểu khác nhau như int trên mệnh đề 1 và nvarchar vào ngày 2. với giải pháp Bob Probst không hoạt động. thanks – Julian50

62

mà không có một tuyên bố trường hợp ...

SELECT column1, column2 
FROM viewWhatever 
WHERE 
    (@locationType = 'location' AND account_location = @locationID) 
    OR 
    (@locationType = 'area' AND xxx_location_area = @locationID) 
    OR 
    (@locationType = 'division' AND xxx_location_division = @locationID) 
+1

Điều này sẽ cho kết quả hơi khác khi câu lệnh Case thoát sau khi điều kiện được đáp ứng - nhưng cú pháp OR sẽ đánh giá tất cả các khả năng – tember

+0

@tember Ngay cả khi SQL là ngôn ngữ thủ tục, nếu OR đầu tiên là true thì phần còn lại của biểu thức không được đánh giá. Vì SQL là một ngôn ngữ khai báo, làm sao bạn biết DBM sẽ đánh giá tất cả các OR? Câu hỏi chân thành, tôi không hiểu. –

+0

Trong SQL, phần còn lại của biểu thức không được đánh giá theo cú pháp OR. Hãy thử điều này (nó sẽ không cho phép tôi bao gồm biểu tượng @ - bạn sẽ phải sửa nó nếu bạn muốn kiểm tra): khai báo var varchar (5) đặt var = '0' chọn 2/var trong đó var <> 0 hoặc ISNUMERIC (var) = 1 . Tôi muốn điều kiện để thoát vì var IS bằng 0, nhưng nó đi trước để kiểm tra xem nó là số, nó là gì, và do đó câu lệnh trả về một lỗi. – tember

3

Vui lòng thử truy vấn này. trả lời Để bài trên:

select @msgID, account_id 
    from viewMailAccountsHeirachy 
    where 
    CASE @smartLocationType 
     WHEN 'store' THEN account_location 
     WHEN 'area' THEN xxx_location_area 
     WHEN 'division' THEN xxx_location_division 
     WHEN 'company' THEN xxx_location_company 
    END = @smartLocation 
+1

Cho bất kỳ ai đọc điều này trong tương lai: nó giống như câu trả lời được chấp nhận từ @ bob-prost ở trên: http://stackoverflow.com/a/206500/264786 –

2

Hãy thử điều này:

WHERE (
    @smartLocationType IS NULL 
    OR account_location = (
     CASE 
      WHEN @smartLocationType IS NOT NULL 
       THEN @smartLocationType 
      ELSE account_location 
     END 
    ) 
) 
+0

Bị bỏ phiếu vì tôi không hiểu cách thức này có thể chọn giữa các chuỗi đã cho (tức là 'vị trí', 'khu vực', 'phân chia') –

-2

Hãy thử truy vấn này. Nó rất dễ hiểu:

CREATE TABLE PersonsDetail(FirstName nvarchar(20), LastName nvarchar(20), GenderID int); 
GO 

INSERT INTO PersonsDetail VALUES(N'Gourav', N'Bhatia', 2), 
       (N'Ramesh', N'Kumar', 1), 
       (N'Ram', N'Lal', 2), 
       (N'Sunil', N'Kumar', 3), 
       (N'Sunny', N'Sehgal', 1), 
       (N'Malkeet', N'Shaoul', 3), 
       (N'Jassy', N'Sohal', 2); 
GO 

SELECT FirstName, LastName, Gender = 
    CASE GenderID 
    WHEN 1 THEN 'Male' 
    WHEN 2 THEN 'Female' 
    ELSE 'Unknown' 
    END 
FROM PersonsDetail 
+0

Cho bất kỳ ai đọc câu trả lời này: nó giống như câu trả lời được chấp nhận từ @ bob-prost ở trên: http://stackoverflow.com/a/206500/264786 Bị bỏ rơi vì lý do này. –

-1
Case Statement in SQL Server Example 

Syntax 

CASE [ expression ] 

    WHEN condition_1 THEN result_1 
    WHEN condition_2 THEN result_2 
    ... 
    WHEN condition_n THEN result_n 

    ELSE result 

END 

Example 

SELECT contact_id, 
CASE website_id 
    WHEN 1 THEN 'TechOnTheNet.com' 
    WHEN 2 THEN 'CheckYourMath.com' 
    ELSE 'BigActivities.com' 
END 
FROM contacts; 

OR 

SELECT contact_id, 
CASE 
    WHEN website_id = 1 THEN 'TechOnTheNet.com' 
    WHEN website_id = 2 THEN 'CheckYourMath.com' 
    ELSE 'BigActivities.com' 
END 
FROM contacts; 
+2

Bị bỏ phiếu vì người trả lời này không liên quan đến câu hỏi.Câu hỏi đặt ra là cách sử dụng CASE trên mệnh đề WHERE, không phải cách sử dụng CASE trên cột đã chọn. –

4

toán tử OR có thể thay thế các trường hợp khi ở nơi mà điều kiện

ALTER PROCEDURE [dbo].[RPT_340bClinicDrugInventorySummary] 
    -- Add the parameters for the stored procedure here 
    @ClinicId BIGINT = 0, 
    @selecttype int, 
    @selectedValue varchar (50) 
AS 
BEGIN 
-- SET NOCOUNT ON added to prevent extra result sets from 
-- interfering with SELECT statements. 
SET NOCOUNT ON; 
SELECT 
    drugstock_drugname.n_cur_bal,drugname.cdrugname,clinic.cclinicname 

FROM drugstock_drugname 
INNER JOIN drugname ON drugstock_drugname.drugnameid_FK = drugname.drugnameid_PK 
INNER JOIN drugstock_drugndc ON drugname.drugnameid_PK = drugstock_drugndc.drugnameid_FK 
INNER JOIN drugndc ON drugstock_drugndc.drugndcid_FK = drugndc.drugid_PK 
LEFT JOIN clinic ON drugstock_drugname.clinicid_FK = clinic.clinicid_PK 

WHERE (@ClinicId = 0 AND 1 = 1) 
    OR (@ClinicId != 0 AND drugstock_drugname.clinicid_FK = @ClinicId) 

    -- Alternative Case When You can use OR 
    AND ((@selecttype = 1 AND 1 = 1) 
    OR (@selecttype = 2 AND drugname.drugnameid_PK = @selectedValue) 
    OR (@selecttype = 3 AND drugndc.drugid_PK = @selectedValue) 
    OR (@selecttype = 4 AND drugname.cdrugclass = 'C2') 
    OR (@selecttype = 5 AND LEFT(drugname.cdrugclass, 1) = 'C')) 

ORDER BY clinic.cclinicname, drugname.cdrugname 
END 
Các vấn đề liên quan