T-SQL 根据另一 table 列过滤一列上的多个值

T-SQL Filter multiple values on one column based on another table column

请帮忙。

我正在使用 SQL 服务器并且熟悉 CONTAINS 关键字。

我有一个 table "Table1" 列值像

1,'bla1 bla2 bla3 String1 bla4 bla5 bla6 String2 bla7 bla8 bla9'
2,'bla3 String1 bla4 String2 bla7 bla8 bla1'
3,'bla3 String2 bla4 String3'

我有另一个 table "Table2" 只有一列,但动态值如

1,bla1
2,string1
3,bla3

1,string2
2,bla5
3,bla1
4,bla4

我只是想 return Table1 中的行基于 Table2 中存在的所有值,这意味着它不是 OR,而是 AND - Table2 中的所有值应出现在表 1 的列值中(可以按任何顺序排列)。

在上面的例子中,

因为表 2 中的值之一在表 1 的列值中不可用

因为这两个 table 都是临时的 table 变量,我无法在它们上面添加 FULL-TEXT INDEX,否则我可以使用 CONTAINS(Column, 'SearchString1 AND SearchString2 AND SearchString3 AND so on')

以下代码工作正常,但最多只能有 2 个搜索字符串。超过2个,就不行了。例如,如果我在下面的代码中有这样的代码

declare @str nvarchar(100) = ' Dr clark Nick '

DECLARE @Tab TABLE(Col NVARCHAR(50))
INSERT INTO @Tab
SELECT ' Dr. Nick Clark' UNION ALL
SELECT ' Dr. Nick SPACE Clark' UNION ALL
SELECT ' Dr. Clark SPACE Nick' UNION ALL
SELECT ' Dr. Clark Nick' UNION ALL
SELECT ' Dr. Nick' UNION ALL
SELECT ' Dr. Clark '

declare @str nvarchar(100) = '  Nick clark '

set @str = ltrim(rtrim(@str))

DECLARE @Search1 VARCHAR(MAX), @Search2 VARCHAR(MAX) 

declare @t table(sno int, splitdata nvarchar(100))
insert into @t
SELECT 
    row_number() over (order by ltrim(rtrim(o.splitdata))) as sno,
    ltrim(rtrim(o.splitdata)) AS splitdata
FROM
    (SELECT CAST('<X>'+REPLACE(@str,' ','</X><X>')+'</X>' AS XML) AS Filter)F1
     CROSS APPLY
          ( SELECT fdata.D.value('.','varchar(MAX)') AS splitdata 
          FROM f1.Filter.nodes('X') AS fdata(D)
    ) O

SELECT @Search1 = COALESCE(@Search1 + '%', '') + Splitdata FROM @t order by sno
SELECT @Search2 = COALESCE(@Search2 + '%', '') + Splitdata FROM @t order by sno desc

select * from @tab where col like '%'+@Search1+'%' or col like '%'+@Search2+'%'

set nocount on;

declare @Tab table (col nvarchar(50));

insert @Tab (Col)
values (' Dr. Nick Clark')
     , (' Dr. Nick SPACE Clark')
     , (' Dr. Clark SPACE Nick')
     , (' Dr. Clark Nick')
     , (' Dr. Nick')
     , (' Dr. Clark ');

declare @str nvarchar(100) = '  Nick clark ';
set @str = ' ' + ltrim(rtrim(@str)) + ' ';

with Tally
as (
    select row_number() over (order by t1.column_id) as 'N'
      from sys.columns t1
      join sys.columns t2
        on 1=1
   )
, Needles
as (
    select substring(@str,N+1,charindex(' ',@str,N+1)-N-1) 'Needle'
      from Tally
     where N < len(@str)
       and substring(@str,N,1) = ' '
   )
, NotSelected
as (
    select tab.col
      from @tab tab
      join Needles
        on 1=1
     where charindex(Needles.Needle,tab.col) = 0
   )
   select Tab.Col
     from @Tab Tab
left join NotSelected
       on NotSelected.Col = Tab.Col
    where NotSelected.Col is null;

好的,这是我的方法:我们将您的搜索字符串变成一个记录集,按 spaces 分解。我对此使用 Tally-table 方法,但我使用基于 sys.columns 的 Common Table Expression 而不是 Real tally table ... 基本上给了我一个table 充满了整数,我可以使用它们快速将 space 分隔的字符串分离到记录集中。我称它为 Needles 是因为我们正在@tab haystack 中寻找这些针。

我创建了针和干草堆的笛卡尔记录集以及 haystackneedle 第一个位置的 CHARINDEX 值。任何零值都告诉我针不在大海捞针中。这也是一个常见的 table 表达式,称为 "NotSelected"- 现在列出所有未找到针的 @Tab.Col 值。

最后,将未选择的行与完整的 table 左连接将显示所有与未选择的值不匹配的记录。