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
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
回答:
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)
[Err] 42000 - [SQL Server]Must declare the scalar variable "@mylist".
(VALUES (1),(2),(3),(4),(5))
直接使用できますか?
TSQLクエリの動的csvリストに取り組む方法は2つあります。
1)内部選択の使用
SELECT * FROM myTable WHERE myColumn in (SELECT id FROM myIdTable WHERE id > 10)
2)動的に連結されたTSQLの使用
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
3)可能な3番目のオプションはテーブル変数です。SQl Server 2005を使用している場合は、テーブル変数を使用できます。SQL Server 2008の場合、テーブル変数全体をパラメータとしてストアドプロシージャに渡し、結合で使用したり、IN句の副選択として使用したりすることもできます。
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)
次のような関数を使用します。
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レコードテーブルでは、2番目のバージョンの所要時間は約半分でした...
乾杯
@LukeHのわずかな改善、 "INSERT INTO"を繰り返す必要はありません:@realPTの答え-SELECTを持つ必要はありません:
DECLARE @MyList TABLE (Value INT)
INSERT INTO @MyList VALUES (1),(2),(3),(4)
SELECT * FROM MyTable
WHERE MyColumn IN (SELECT Value FROM @MyList)
私はこれが古いことを知っていますが、TSQL => 2016、STRING_SPLITを使用できます:
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)
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,','))
2番目のテーブルを使用せずにこれを行う場合は、CASTを使用してLIKE比較を行うことができます。
DECLARE @myList varchar(15)
SET @myList = ',1,2,3,4,'
SELECT *
FROM myTable
WHERE @myList LIKE '%,' + CAST(myColumn AS varchar(15)) + ',%'
比較するフィールドが既に文字列の場合、CASTする必要はありません。
列の一致と各一意の値の両方をコンマで囲むと、完全に一致します。そうでない場合、値「1」は、「、4,2,15、」を含むリストで見つかります。
以前に誰も言及しなかったように、Sql Server 2016からは、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
jsonでより複雑なケースを簡単にカバーすることもできます。SQL変数でWHERE IN句を使用してSQLの値と範囲のリストを検索するをご覧ください。
これは、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
ノート:
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;
文字列を宣言してから、そのSQL文字列を実行する必要があると思います。