SQL子句/ case在where子句中

Mil*_*les 142 sql case switch-statement

我试着四处寻找但找不到任何可以帮助我的东西.

我正在尝试在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
Run Code Online (Sandbox Code Playgroud)

我知道我不应该在每个人的末尾放置'= @locationID',但我无法使语法接近正确.SQL在第一条WHEN行上一直抱怨我的'='

救命!

Bob*_*bst 186

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
Run Code Online (Sandbox Code Playgroud)

  • @表示t-sql中的变量,如果没有@,则@locationID将被解释为列名。 (2认同)

Luk*_*kek 69

没有案例陈述......

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)
Run Code Online (Sandbox Code Playgroud)

  • 这将给出稍微不同的结果,因为 Case 语句在满足条件后退出 - 但 OR 语法将评估所有可能性 (2认同)
  • 在 SQL 中,表达式的其余部分确实以 OR 语法进行计算。试试这个(它不会让我包含@符号 - 如果你想测试它,你必须更正它):declare var varchar(5) set var = '0' select 2 / var where var <> 0 or ISNUMERIC(var) = 1 。我希望条件退出,因为 var IS 等于 0,但它会继续检查它是否是数字(确实如此),因此该语句返回错误。 (2认同)

Pit*_*DBA 32

干得好.

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
Run Code Online (Sandbox Code Playgroud)

  • 好吧,我会把它写成SELECT column1,column2 FROM viewWhatever WHERE(@locationType ='location'和account_location = @locationID)OR(@locationType ='area'AND xxx_location_area = @locationID)OR(@locationType ='division' AND xxx_location_division = @locationID) (5认同)
  • 这是一个很好的和平的例子,如何查询执行计划与最好的答案(个人我更喜欢这个方法代码清晰干净) (2认同)
  • 如果您想使用不同类型的不同 where 子句(例如第一个子句上的 int 和第二个子句上的 nvarchar),这真的很棒。鲍勃·普罗布斯特的解决方案是行不通的。谢谢 (2认同)

Mar*_*sen 6

我会说这是一个有缺陷的表结构的指标.也许不同的位置类型应该在不同的表中分开,这使您可以进行更丰富的查询,并避免使用多余的列.

如果您无法更改结构,则可能会执行以下操作:

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
    )
Run Code Online (Sandbox Code Playgroud)

等等...我们无法动态更改查询的结构,但我们可以通过使谓词等于自己来覆盖它.

编辑:以上建议当然要好得多,只是忽略我的.


Dil*_*e-O 5

这样做的问题是,当SQL引擎去评估表达式时,它将检查FROM部分以提取适当的表,然后检查WHERE部分以提供一些基本条件,因此它无法正确地评估要在哪一列上使用的动态条件。检查。

在检查谓词中的WHERE条件时,可以使用WHERE子句,例如

WHERE account_location = CASE @locationType
                              WHEN 'business' THEN 45
                              WHEN 'area' THEN 52
                         END
Run Code Online (Sandbox Code Playgroud)

因此,在您的特定情况下,您需要将查询放入存储过程或创建三个单独的查询。


ati*_*ker 5

在运行条件的情况下,OR运算符可以替代大小写

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
Run Code Online (Sandbox Code Playgroud)