2015-12-16 121 views
1

請幫忙。T-SQL基於另一個表列在一列上過濾多個值

我正在使用SQL Server並熟悉CONTAINS關鍵字。

我有一個表「表1」的字段值一樣

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' 

我有另一個表「表2」只有一列,但與動態值一樣

1,bla1 
2,string1 
3,bla3 

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

我只想根據Table2中存在的所有值返回Table1中的行,表示它不是OR,而是AND - Table2中的所有值都應出現在Table1的列值中(它可以按任意順序)。

在上述例子中,

  • 如果表2的第一組抵靠表1選中,那麼它應該從表1
  • 如果表2的第二組抵靠表1檢查只返回前2行,則它應該如表2中的一個值返回表1

只有第一排並不在表1的列值可用。

由於這兩個表是臨時表變量,我無法對它們添加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 '%'[email protected]+'%' or col like '%'[email protected]+'%' 

+0

如果table1上的一行是「NickClarkNick」(沒有空格),你會期待匹配嗎? –

+0

尼克或克拉克的任何數量都沒問題......但尼克和克拉克應該在場......有或沒有空格。 – bkar81

回答

0
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; 

好了,這裏是我的方法:我們將您的搜索字符串的記錄,通過細分空間。我使用Tally-table的方法來實現這個功能,但是我使用的是基於sys.columns的Common Table Expression ......基本上給了我一張充滿整數的表格,我可以用它來快速分離出你的空間分隔字符串轉換爲記錄集。我稱之爲Needles,因爲我們正在@tab乾草堆中尋找這些針。

我創建了針笛和乾草堆的笛卡爾記錄集以及needle的第一個位置的CHARINDEXhaystack。任何零值都告訴我,針不在乾草堆裏。這也是一個常見的表格表達式,稱爲「NotSelected」 - 現在列出找不到針的所有@ Tab.Col值。

最後,「未選定」行與全表的左連接將顯示與「未選定」值不匹配的所有記錄。

+0

哇......它的工作原理......我剛剛測試過數值(置換和組合)。 。 然而,瞭解邏輯... 感謝您的解決方案... – bkar81

+0

明白了現在...... 改名爲熱膨脹係數我的理解爲「SNo_Gen」,「Search_Str_Splitter」和「Not_Exists」的邏輯(從從上到下)...... 再次感謝。 – bkar81

相關問題