带有IN子句值列表的TSQL变量

Zac*_*eth 10 t-sql sql-server

我想在select语句中使用"CASE WHEN ... THEN 1 ELSE 0 END"的句子.棘手的部分是我需要它与"值IN @List"一起使用.

如果我硬编码列表它工作正常 - 它表现良好:

SELECT
       CASE WHEN t.column_a IN ( 'value a', 'value b' ) THEN 1 ELSE 0 END AS priority
      , t.column_b
      , t.column_c
  FROM
       table AS t
 ORDER BY
       priority DESC
Run Code Online (Sandbox Code Playgroud)

我想做的是:

-- @AvailableValues would be a list (array) of strings.
DECLARE
        @AvailableValues ???

 SELECT
        @AvailableValues = ???
   FROM
        lookup_table

 SELECT
        CASE WHEN t.column_a IN @AvailableValues THEN 1 ELSE 0 END AS priority
      , t.column_b
      , t.column_c
   FROM
        table AS t
  ORDER BY
        priority DESC
Run Code Online (Sandbox Code Playgroud)

不幸的是,似乎SQL Server没有这样做 - 你不能使用带有IN子句的变量.所以这给我留下了一些其他选择:

  1. 使'@AvailableValues'成为逗号分隔的字符串并使用LIKE语句.这不是很好.
  2. 对"lookup_table"使用内联SELECT语句代替变量.再次,表现不佳(我认为),因为它必须在每一行上查找表.
  3. 编写一个包围SELECT语句的函数来代替变量.我还没有尝试过(现在就试试)但似乎它会遇到与直接SELECT语句相同的问题.
  4. ???

还有其他选择吗?性能对于查询非常重要 - 它必须非常快,因为它为网站提供实时搜索结果页面(即没有缓存).

这里还有其他选择吗?有没有办法改善上述选项之一的性能以获得良好的性能?

在此先感谢您提供的任何帮助!

更新:我应该提到上例中的'lookup_table'已经是一个表变量.我还更新了示例查询,以更好地演示我如何使用该子句.

更新II:我发现IN子句在NVARCHAR/NCHAR字段下运行(由于历史表设计原因).如果我要进行处理整数字段的更改(即通过PK/FK关系约束),这会对性能产生很大影响吗?

Ada*_*son 7

您可以在IN子句中使用变量,但不能按照您尝试的方式使用.例如,你可以这样做:

declare @i int
declare @j int

select @i = 10, @j = 20

select * from YourTable where SomeColumn IN (@i, @j)
Run Code Online (Sandbox Code Playgroud)

关键是变量不能代表多个值.

要回答您的问题,请使用内联选择.只要您不在查询中引用外部值(可能会按行更改结果),引擎就不会重复从表中选择相同的数据.