子句在参数中查找字符串的情况

时间:2018-10-31 10:02:45

标签: sql-server string parameters case where-clause

我的数据库tblCustomer中有一个表,其中有8个布尔字段(MS01,MS02 ... MS08) 使用SSRS报告,我有一个多值参数下拉列表,可以选择10个值中的每一个 因此,如果我从列表中选择MS01和MS05,则参数@idSite将等于'MS01','MS05'

'-1'=真

我想从tblCustomer中选择所有参数值为真的记录

select idCustomer, MS01, MS02,MS03, MS04,MS05,MS06,MS07,MS08 from tblCustomer

WHERE     (tblCustomer.CustomerYN = '-1')
AND
CASE 
WHEN  @idSite like '%MS01%' THEN  tblCustomer.MS01=-1 
WHEN  @idSite like '%MS02%' THEN  tblCustomer.MS02=-1
WHEN  @idSite like '%MS03%' THEN  tblCustomer.MS03=-1
END as MailShot

我还尝试使用字符串在参数表中的时间

select idCustomer, MS01, MS02,MS03, MS04,MS05,MS06,MS07,MS08 from 
tblCustomer

WHERE     (tblCustomer.CustomerYN = '-1')
AND
CASE 
WHEN  'MS01' in @idSite THEN  tblCustomer.MS01=-1 
WHEN  'MS02' in @idSite THEN  tblCustomer.MS02=-1

END as MailShot

我以为我与上述观点相近,但没有喜悦。谁能指出我正确的方向?

编辑

@idSite是SSRS多值参数下拉列表。

下拉列表中的部分根据下表中的值获取idMailshot值
idMailShot  Location
MS01    Location1   
MS02    Location2     
MS03    Location3 
MS04    Location4  
MS05    Location5  
MS06    Location6     
MS07    Location7   
MS08    Location8   
MS09    Location9

因此,如果我从下拉列表中选择Location1和Location 2,则应将“ MS01,MS02”作为@idSite传递 我想

select idCustomer from tblCustomer where
tblCustomer.MS01 =-1 AND tblCustomer.MS02=-1

3 个答案:

答案 0 :(得分:3)

没有这样的方法可以在Sql Server变量中存储多个值,如下所示: dclose = security(tickerid, "D", close[1]) hline (dclose)

但是您可以通过以下方式在变量表中完全填充多个值:

DECLARE @idSite ='MS01','MS02','MS03';

如果您收到的字符串像这样declare @idSites table ( idSite varchar(100) ) insert into @idSites (idSite) select COLUMN_NAME from Information_schema.Columns where TABLE_NAME = 'Table Name' and TABLE_CATALOG = 'Database Name' 那么您需要编写一个函数来基于"MS01,MS02,MS03"分隔值生成表,例如:

comma

然后像这样使用它:

CREATE FUNCTION splitstring ( @stringToSplit VARCHAR(8000) )
    RETURNS
        @returnList TABLE ([Param] [nvarchar] (500))
AS
BEGIN

    DECLARE @name NVARCHAR(255)
    DECLARE @pos INT

    WHILE CHARINDEX(',', @stringToSplit) > 0
    BEGIN
        SELECT @pos  = CHARINDEX(',', @stringToSplit) 
        SELECT @name = SUBSTRING(@stringToSplit, 1, @pos-1)

        INSERT INTO @returnList
        SELECT @name

        SELECT @stringToSplit = SUBSTRING(@stringToSplit, @pos+1, LEN(@stringToSplit)-@pos)
    END
    INSERT INTO @returnList
    SELECT @stringToSplit
    RETURN
END

您的declare @StringVariable varchar(255) = "MS01,MS02,MS03"; Select [param] from splitstring(@StringVariable) 子句也没有多大意义。我在下面编写了一个测试环境,请查看我如何在其中维护WHERE子句。

下面的解决方案是使用假定的数据,您可以将其复制粘贴到WHERE并执行。希望它能帮助您达到所需的要求:)。

SQL Server

答案 1 :(得分:1)

您的WHERE毫无意义:

WHERE     (tblCustomer.CustomerYN = '-1')
AND
CASE 
WHEN  @idSite like '%MS01%' THEN  tblCustomer.MS01=-1 
WHEN  @idSite like '%MS02%' THEN  tblCustomer.MS02=-1
WHEN  @idSite like '%MS03%' THEN  tblCustomer.MS03=-1
END as MailShot

您整体上的CASE表达式不是布尔表达式,它在THEN中包含布尔表达式; CASE返回标量值而不是布尔值。您还为CASE中的WHERE加上了别名。您无需在WHERE中为表达式加上别名。

但是,与其使用CASE表达式(这会使查询不可SARG),不如使用布尔逻辑会更好:

WHERE tblCustomer.CustomerYN = -1 -- -1 is a int, pass it as one
  AND ((tblCustomer.MS01 = -1 AND @idSite like '%MS01%')
   OR  (tblCustomer.MS02 = -1 AND @idSite like '%MS02%')
   OR  (tblCustomer.MS03 = -1 AND @idSite like '%MS03%'))

请注意,如果您在CASE内使用WHERE表达式(尽管,就像我在上面说的那样,这将导致它不可SARG),则需要返回一个标量值并创建一个布尔表达式。举一个简单的例子:

WHERE CASE @SomeID WHEN 1 THEN T.ColumnA
                   WHEN 2 THEN T.ColumnB
                   ELSE T.ColumnC
      END = 'Some Value'

请注意,CASE表达式返回标量值(ColumnAColumnBColumnC的值),然后该标量值为与文字字符串'Some Value'相比。您的布尔表达式不在THEN表达式中,而是在CASE表达式之外。

答案 2 :(得分:0)

如果您想通过值传递您的工作方式。您需要一个拆分功能。因为找不到您的值组合。在这种情况下,您尝试将列标题值与存储在单元格中的值进行比较。

DECLARE @idSite ='MS01','MS02','MS03';

您的替代方法是使用CTE快速构建查找表,然后在报表proc开始时将数据转储到temp表中。它将执行10个值的组合并存储它们。然后,您可以在filter子句中动态利用此临时表。请记住“联接”条件(即您将从主表联接回该临时表的列)。