2013-10-31 114 views
1

如果我有一个颜色主列表(nvarchar字段),并且我想检查小列表中的任何项目是否在主列表中(nvarchar字段)。T-SQL:检查一个小列表中的项目是否在大列表中

例如主列表'red |橙色|绿色|蓝色|白”

  1. | 橙色”=>真

  2. 白色 | 绿色”=>真

  3. |黑色“=> true

  4. “black |黄色” =>假

  5. “黄色”=>假

什么是T-SQL来解决它的最好方法?

谢谢。

+2

*在T-SQL中解决这个问题的最好方法是什么?*以关系格式存储数据。 –

+0

对不起,我无法改变现有的数据格式。 – seanbun

回答

2

这是使用一个简单的解决方案:

  1. Table-Valued User-Defined FunctionXML nodes() method到列表转换成表格。检查
  2. INTERSECT方法,如果从拳头列表中的值包含在第二

这是函数体:

IF EXISTS (SELECT 1 FROM sysobjects WHERE id = object_id(N'fn_ConvertListToNVarcharTable') AND xtype IN (N'FN', N'IF', N'TF')) 
BEGIN 
    DROP FUNCTION [dbo].[fn_ConvertListToNVarcharTable] 
END 
GO 

SET ANSI_NULLS ON 
GO 

SET QUOTED_IDENTIFIER ON 
GO 

CREATE FUNCTION [dbo].[fn_ConvertListToNVarcharTable] (@List nvarchar(max)) 
RETURNS @ResultRowset TABLE ([Value] NVARCHAR(250) PRIMARY KEY) 
AS 
BEGIN 
    DECLARE @XML xml = N'<r><![CDATA[' + REPLACE(@List, '|', ']]></r><r><![CDATA[') + ']]></r>' 

    INSERT INTO @ResultRowset ([Value]) 
    SELECT DISTINCT RTRIM(LTRIM(Tbl.Col.value('.', 'nvarchar(250)'))) 
    FROM @xml.nodes('//r') Tbl(Col) 

    RETURN 
END 

GO 

这是一个检查如何进行:

IF EXISTS(
    SELECT [Value] 
    FROM[fn_ConvertListToNVarcharTable]('red | orange') 
    INTERSECT 
    SELECT [Value] 
    FROM [fn_ConvertListToNVarcharTable]('red | orange | green | blue | white') 
) 
BEGIN 
    SELECT 'True' 
END 
ELSE 
BEGIN 
    SELECT 'False' 
END 
+1

+1虽然我会努力检查一个班轮,所以它也可以用于表 –

+0

@ t-clausen.dk这很好。在某些情况下,内联用户功能可以提高多线程性能。 – gotqn

3

您可以创建一个表值函数为:

create table tblMaster(color nvarchar(4000)); 
insert into tblMaster values ('red | orange | green | blue | white'); 
Go 

-- Create a function to return data as rows of table. 
CREATE FUNCTION [dbo].[SplitString](@String varchar(max), @Delimiter char(1)) 
returns @temptable TABLE (items varchar(max)) 
as 
begin 
    declare @idx int 
    declare @slice varchar(max) 

    select @idx = 1 
     if len(@String)<1 or @String is null return 

    while @idx!= 0 
    begin 
     set @idx = charindex(@Delimiter,@String) 
     if @idx!=0 
      set @slice = left(@String,@idx - 1) 
     else 
      set @slice = @String 

     if(len(@slice)>0) 
      insert into @temptable(Items) values(@slice) 

     set @String = right(@String,len(@String) - @idx) 
     if len(@String) = 0 break 
    end 
return 
end 
Go 

然后写下如下查询来得到想要的结果:

Declare @color_mstr_list nvarchar(4000),@color_small_list nvarchar(4000); 
select @color_mstr_list = color from tblMaster ; 

select items into #temp from [dbo].[SplitString](@color_mstr_list,'|'); 

set @color_small_list = 'red | black'; 

with cte as 
( 
select items from [dbo].[SplitString](@color_small_list,'|') 
) 
select case when COUNT(*) > 0 then 'True' 
      else 'False' 
      end as Result 
from cte 
where exists (select * from #temp T where T.items = cte.items) 

drop table #temp; 
相关问题