【问题标题】:T-SQL: Check if an item in a small list is in a big listT-SQL:检查小列表中的项目是否在大列表中
【发布时间】:2013-10-31 17:10:14
【问题描述】:

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

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

  1. "红色 | 橙色" => true

  2. "白色 | 绿色" =>真

  3. "红色 | 黑色" => 真

  4. “黑色|黄色”=> 错误

  5. “黄色”=> 错误

在 T-SQL 中解决此问题的最佳方法是什么?

谢谢。

【问题讨论】:

  • 在 T-SQL 中解决此问题的最佳方法是什么? 以关系格式存储数据。
  • 抱歉,我无法更改现有的数据格式。

标签: sql-server-2008 tsql


【解决方案1】:

您可以将表值函数创建为:

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;

【讨论】:

    【解决方案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 虽然我会努力检查单线,所以它也可以用在桌子上
    • @t-clausen.dk 这很好。在某些情况下,内联用户函数可以提供比多行函数更好的性能。
    猜你喜欢
    • 1970-01-01
    • 2011-09-02
    • 2017-12-21
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-25
    • 2012-06-30
    相关资源
    最近更新 更多