代码之家  ›  专栏  ›  技术社区  ›  Marcos Crispino

定义要与IN运算符(T-SQL)一起使用的变量

  •  102
  • Marcos Crispino  · 技术社区  · 15 年前

    我有一个使用IN运算符的Transact-SQL查询。像这样:

    select * from myTable where myColumn in (1,2,3,4)
    

    有没有办法定义一个变量来保存整个列表“(1,2,3,4)”?我该如何定义它?

    declare @myList {data type}
    set @myList = (1,2,3,4)
    select * from myTable where myColumn in @myList
    
    12 回复  |  直到 11 年前
        1
  •  118
  •   LukeH    15 年前
    DECLARE @MyList TABLE (Value INT)
    INSERT INTO @MyList VALUES (1)
    INSERT INTO @MyList VALUES (2)
    INSERT INTO @MyList VALUES (3)
    INSERT INTO @MyList VALUES (4)
    
    SELECT *
    FROM MyTable
    WHERE MyColumn IN (SELECT Value FROM @MyList)
    
        2
  •  48
  •   Stefan Z Camilleri pajton    11 年前
    DECLARE @mylist TABLE (Id int)
    INSERT INTO @mylist
    SELECT id FROM (VALUES (1),(2),(3),(4),(5)) AS tbl(id)
    
    SELECT * FROM Mytable WHERE theColumn IN (select id from @mylist)
    
        3
  •  13
  •   hollystyles    8 年前

    有两种方法可以处理TSQL查询的动态csv列表:

    1) 使用内部选择

    SELECT * FROM myTable WHERE myColumn in (SELECT id FROM myIdTable WHERE id > 10)
    

    DECLARE @sql varchar(max)  
    declare @list varchar(256)  
    select @list = '1,2,3'  
    SELECT @sql = 'SELECT * FROM myTable WHERE myColumn in (' + @list + ')'
    
    exec sp_executeSQL @sql
    

    DECLARE @list TABLE (Id INT)
    
    INSERT INTO @list(Id)
    SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
    
    
    SELECT
        * 
    FROM 
        myTable
        JOIN @list l ON myTable.myColumn = l.Id
    
    SELECT
        * 
    FROM 
        myTable
    WHERE
        myColumn IN (SELECT Id FROM @list)
    
        4
  •  9
  •   allaphor    12 年前

    CREATE function [dbo].[list_to_table] (@list varchar(4000))
    returns @tab table (item varchar(100))
    begin
    
    if CHARINDEX(',',@list) = 0 or CHARINDEX(',',@list) is null
    begin
        insert into @tab (item) values (@list);
        return;
    end
    
    
    declare @c_pos int;
    declare @n_pos int;
    declare @l_pos int;
    
    set @c_pos = 0;
    set @n_pos = CHARINDEX(',',@list,@c_pos);
    
    while @n_pos > 0
    begin
        insert into @tab (item) values (SUBSTRING(@list,@c_pos+1,@n_pos - @c_pos-1));
        set @c_pos = @n_pos;
        set @l_pos = @n_pos;
        set @n_pos = CHARINDEX(',',@list,@c_pos+1);
    end;
    
    insert into @tab (item) values (SUBSTRING(@list,@l_pos+1,4000));
    
    return;
    end;
    

    不使用like,而是与函数返回的表进行内部联接:

    select * from table_1 where id in ('a','b','c')
    

    select * from table_1 a inner join [dbo].[list_to_table] ('a,b,c') b on (a.id = b.item)
    

    在一个没有索引的1M记录表中,第二个版本花费了大约一半的时间。。。

        5
  •  5
  •   Volodymyr    6 年前
    DECLARE @myList TABLE (Id BIGINT) INSERT INTO @myList(Id) VALUES (1),(2),(3),(4);
    select * from myTable where myColumn in(select Id from @myList)
    

    请注意,对于长列表或生产系统,不建议使用这种方法,因为它可能比简单的方法慢得多 IN 类运算符 someColumnName in (1,2,3,4)

        6
  •  5
  •   Max Favilli    6 年前

    从SQL2017开始,您可以使用 STRING_SPLIT 这样做:

    declare @myList nvarchar(MAX)
    set @myList = '1,2,3,4'
    select * from myTable where myColumn in (select value from STRING_SPLIT(@myList,','))
    
        7
  •  4
  •   Vilx-    15 年前

    • 动态生成的查询(sp\u executesql)
    • 表类型变量(最接近列表的东西)

        8
  •  4
  •   user5292841 user5292841    6 年前

    @LukeH稍有改进,无需重复“INSERT INTO”: 和@realPT的答案-无需选择:

    DECLARE @MyList TABLE (Value INT) 
    INSERT INTO @MyList VALUES (1),(2),(3),(4)
    
    SELECT * FROM MyTable
    WHERE MyColumn IN (SELECT Value FROM @MyList)
    
        9
  •  4
  •   Nathan Evans    6 年前

    DECLARE @InList varchar(255) = 'This;Is;My;List';
    
    WITH InList (Item) AS (
        SELECT value FROM STRING_SPLIT(@InList, ';')
    )
    
    SELECT * 
    FROM [Table]
    WHERE [Item] IN (SELECT Tag FROM InList)
    
        10
  •  2
  •   Michael Reyes    8 年前

    如果要在不使用第二个表的情况下执行此操作,可以与CAST进行类似的比较:

    DECLARE @myList varchar(15)
    SET @myList = ',1,2,3,4,'
    
    SELECT *
    FROM myTable
    WHERE @myList LIKE '%,' + CAST(myColumn AS varchar(15)) + ',%'
    

    用逗号包围列匹配和每个唯一值将确保精确匹配。否则,将在包含',4,2,15,'的列表中找到值1

        11
  •  1
  •   roman    6 年前

    正如之前没有人提到的,从SQLServer2016开始,您还可以使用json数组和 OPENJSON (Transact-SQL)

    declare @filter nvarchar(max) = '[1,2]'
    
    select *
    from dbo.Test as t
    where
        exists (select * from openjson(@filter) as tt where tt.[value] = t.id)
    

    你可以试一下 sql fiddle demo

    Search list of values and range in SQL using WHERE IN clause with SQL variable?

        12
  •  1
  •   Marne    4 年前

    这一个使用PATINDEX将表中的id与非数字分隔的整数列表进行匹配。

    -- Given a string @myList containing character delimited integers 
    -- (supports any non digit delimiter)
    DECLARE @myList VARCHAR(MAX) = '1,2,3,4,42'
    
    SELECT * FROM [MyTable]
        WHERE 
            -- When the Id is at the leftmost position 
            -- (nothing to its left and anything to its right after a non digit char) 
            PATINDEX(CAST([Id] AS VARCHAR)+'[^0-9]%', @myList)>0 
            OR
            -- When the Id is at the rightmost position
            -- (anything to its left before a non digit char and nothing to its right) 
            PATINDEX('%[^0-9]'+CAST([Id] AS VARCHAR), @myList)>0
            OR
            -- When the Id is between two delimiters 
            -- (anything to its left and right after two non digit chars)
            PATINDEX('%[^0-9]'+CAST([Id] AS VARCHAR)+'[^0-9]%', @myList)>0
            OR
            -- When the Id is equal to the list
            -- (if there is only one Id in the list)
            CAST([Id] AS VARCHAR)=@myList
    

    • %(通配符)将匹配任何零个或多个字符的字符串
    • [^0-9]将匹配任何非数字字符
    • PATINDEX是一个SQL标准函数,返回模式在字符串中的位置
        13
  •  0
  •   Muhammed Fatih Yıldız    8 年前
    DECLARE @StatusList varchar(MAX);
    SET @StatusList='1,2,3,4';
    DECLARE @Status SYS_INTEGERS;
    INSERT INTO  @Status 
    SELECT Value 
    FROM dbo.SYS_SPLITTOINTEGERS_FN(@StatusList, ',');
    SELECT Value From @Status;
    
        14
  •  -1
  •   Lavish Saluja BIDeveloper    5 年前

    看一看 sp_executeSQL