Sql 将数据存储在两个CSV字符串和两个db表中,以实现最快的比较

Sql 将数据存储在两个CSV字符串和两个db表中,以实现最快的比较,sql,sql-server,csv,Sql,Sql Server,Csv,情况是,我们有两个列表: A:23,45,g5,33 B:11,12,45,g9 我们希望SQL SERVER中最快的机制可以查看B中的任何值是否在A中可用,在本例中,45在A中,因此它必须返回true 解决方案应描述存储列表(CSV、表格等)的方式和比较机制 每个列表都相对较小(平均每个列表中有10个值),但进行了多次比较(很少写入,多次读取)我仍然对核心思想感到困惑。。。但这里有一个比逗号分隔列表更好的简单解决方案。当然,创建索引会使它更快。这比循环快得多 declare @table ta

情况是,我们有两个列表:

A:23,45,g5,33

B:11,12,45,g9

我们希望SQL SERVER中最快的机制可以查看B中的任何值是否在A中可用,在本例中,45在A中,因此它必须返回true

解决方案应描述存储列表(CSV、表格等)的方式和比较机制


每个列表都相对较小(平均每个列表中有10个值),但进行了多次比较(很少写入,多次读取)

我仍然对核心思想感到困惑。。。但这里有一个比逗号分隔列表更好的简单解决方案。当然,创建索引会使它更快。这比循环快得多

declare @table table (id char(4), v varchar(256))
insert into @table
values
('A','23'),
('A','45'),
('A','g5'),
('A','33'),
('B','11'),
('B','12'),
('B','45'),
('B','g9')


select distinct
    base.v
    --,base.*
    --,compare.*
from 
    @table base
inner join
    @table compare
    on compare.v = base.v
    and compare.id <> base.id

如果您被分隔的字符串所困扰,请考虑以下内容:

示例:

Declare @YourTable Table ([ColA] varchar(50),[ColB] varchar(50))
Insert Into @YourTable Values 
 ('23,45,g5,33' ,'11,12,45,g9')
,('no,match'    ,'found,here')


Select * 
 from @YourTable A
 Cross Apply (
                Select Match=IsNull(sum(1),0)
                 From  [dbo].[udf-Str-Parse-8K](ColA,',') B1
                 Join  [dbo].[udf-Str-Parse-8K](ColB,',') B2 on B1.RetVal=B2.RetVal
             ) B
返回

ColA          ColB          Match
23,45,g5,33   11,12,45,g9   1
no,match      found,here    0
UDF如果感兴趣

CREATE FUNCTION [dbo].[udf-Str-Parse-8K] (@String varchar(max),@Delimiter varchar(25))
Returns Table 
As
Return (  
    with   cte1(N)   As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
           cte2(N)   As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
           cte3(N)   As (Select 1 Union All Select t.N+DataLength(@Delimiter) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter)) = @Delimiter),
           cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter,@String,s.N),0)-S.N,8000) From cte3 S)

    Select RetSeq = Row_Number() over (Order By A.N)
          ,RetVal = LTrim(RTrim(Substring(@String, A.N, A.L)))
    From   cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')

根据前面的答案,我认为应该是这样的:

declare @table table (id char(4), v varchar(256))
insert into @table
values
('A','23'),
('A','45'),
('A','g5'),
('A','33'),
('B','11'),
('B','12'),
('B','45'),
('B','g9')


if exists( select count(1)
        from 
            @table base
        inner join
            @table compare
            on compare.v = base.v
            and base.id='A' and compare.id='B') 
 print 'true'
 else
 print 'false'

根据数据量的增长,在id、v或v、id上建立索引?索引表应该是最快的两个列表?你是说两列?如何将它们存储在同一列中,并为您要拆分的内容指定一个ID。您尚未声明此数据是否已在SQL Server中。但是,一般来说,不要在SQLServer中将值存储为逗号分隔的字符串。无论如何,您都必须将其拆分以进行比较。如果您要求将其存储在不同的表中,而不是同一个表和不同的列中,那么这个问题很奇怪。相同的表会更快,但这不是设计数据库时要问的问题通常是关系和规范化XY问题是关于您尝试的解决方案而不是实际问题。描述你的真实情况,而不是简单明了的解决方法。停止像这样存储分隔数据。它违反1NF,使查询变得更加困难和缓慢。不错,但它比@scsimon answer快吗?@mohas很难说。仍然不是100%清楚。你在寻找任何字符串中的匹配项吗?如果是的话,我有一个alternative@mohas如果没有别的,提供的解析函数是最快的方法之一,请分享
CREATE FUNCTION [dbo].[udf-Str-Parse-8K] (@String varchar(max),@Delimiter varchar(25))
Returns Table 
As
Return (  
    with   cte1(N)   As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
           cte2(N)   As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 a,cte1 b,cte1 c,cte1 d) A ),
           cte3(N)   As (Select 1 Union All Select t.N+DataLength(@Delimiter) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter)) = @Delimiter),
           cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter,@String,s.N),0)-S.N,8000) From cte3 S)

    Select RetSeq = Row_Number() over (Order By A.N)
          ,RetVal = LTrim(RTrim(Substring(@String, A.N, A.L)))
    From   cte4 A
);
--Orginal Source http://www.sqlservercentral.com/articles/Tally+Table/72993/
--Select * from [dbo].[udf-Str-Parse-8K]('Dog,Cat,House,Car',',')
--Select * from [dbo].[udf-Str-Parse-8K]('John||Cappelletti||was||here','||')
declare @table table (id char(4), v varchar(256))
insert into @table
values
('A','23'),
('A','45'),
('A','g5'),
('A','33'),
('B','11'),
('B','12'),
('B','45'),
('B','g9')


if exists( select count(1)
        from 
            @table base
        inner join
            @table compare
            on compare.v = base.v
            and base.id='A' and compare.id='B') 
 print 'true'
 else
 print 'false'