2014-11-05 95 views
0

我已经广泛搜索了相关的答案,但都没有完全满足我需要做的事情。在SQL Server中解析/索引二进制字符串

为了我们的目的,我有一个包含50个字符的二进制字符串的列。在我们的数据库中,它实际上有数百个字符。

我们的数据库中每个唯一的物品ID都有一个字符串。每个'1'的位置标记一个特定的标准为真,'0'为假,因此这些零和零的索引位置非常重要。大多数情况下,我关心1的位置。

我不更新任何数据库,所以我第一次决定尝试做一个循环来查看每串并创造1的位置的列表。

declare @binarystring varchar(50) = '10000010000110000001000000000000000000000000000001' 
declare @position int = 0 
declare @list varchar(200) = '' 

while (@position <= len(@binarystring)) 
begin 

set @position = charindex('1', @binarystring, @position) 
set @list = @list + ', ' + convert(varchar(10),@position) 
set @position = charindex('1', @binarystring, @position)+1 

end 
select right(@list, len(@list)-2) 

这将创建以下列表:

1, 7, 12, 13, 20, 50 

然而,循环将轰炸,如果没有“1”在字符串的结尾,因为我通过串通过事件搜索而不是一次一个字符。我不知道如何满足中断标准,当循环通常会到达字符串的末尾,而不存在1.

有没有一个简单的解决方案,我的循环轰炸,我应该在第一个循环地点?

我试图解析的其他方法,联合加盟,索引等,但考虑到这个非常具体的情况下,我无法找到我确实很需要什么样的任意组合。上面的代码是迄今为止我所掌握的最好的代码。

我并不特别需要分隔的列表作为输出一个逗号,但我需要知道在字符串中全部为1的位置。 1的数量不尽相同,但字符串大小始终相同。

这是我第一次张贴到计算器,但我已经使用的答案很多次。我试图用相关信息给出一个明确的问题。如果有什么我可以帮忙的,我会尽力满足任何要求。

回答

0

如何将while条件更改为此?

while (charindex('1', @binarystring, @position) > 0) 
+0

这种固定没有问题的伟大工程在字符串的末尾有一个1,但是如果字符串中没有1,就会弹出。有没有好的抓住所有这一切?也许是个案陈述? – 2014-11-06 14:08:10

+0

@Muffin_Cup。 。 。在这种情况下,这个“炸弹”将如何?如果发生这种情况,那么'@ list'将是空的。 – 2014-11-06 18:46:49

0
while (@position <= len(@binarystring)) 
begin 
     set @position = charindex('1', @binarystring, @position) 
     if @position != 0 
     begin 
      set @list = @list + ', ' + convert(varchar(10),@position) 
      set @position = charindex('1', @binarystring, @position)+1 
     end 
     else 
     begin 
      break 
     end; 
end 
+0

当没有找到最后1时,中断将你从循环中移出并停止它从字符串的from开始重新开始。 – 2014-11-05 22:33:43

+0

这个循环也适用,但如果在字符串中找不到1(全为零),它会发生炸弹 - 对此有一个很好的解决方案吗? – 2014-11-06 14:39:23

+0

在循环之前,如果(charindex('1',@binarystring,@position)> 0 - 然后将while循环放入一个简单的检查是否存在任何1的 – 2014-11-06 15:00:27

0

常常是有用的有得心应手的顺序整数的大范围的来源。我有一张表,dbo.range,它有一列,id包含从-500,000到+500,000的所有顺序整数。该列是一个集群主键,因此查找速度很快。用这样的表格,解决你的问题很容易。

假设你的表有一个模式类似

create table dbo.some_table_with_flags 
(
    id int   not null primary key , 
    flags varchar(1000) not null , 
) 

下面的查询应该做你:

select row_id  = t.id , 
     flag_position = r.id 
from dbo.some_table t 
join dbo.range  r on r.id between 1 and len(t.flags) 
        and substring(t.flags,r.id,1) = '1' 

对于在flags列中的每个1值,你会得到包含一行来自源表格ID列的ID以及在flags中找到1的位置。

有许多技术可以生成这样的序列。此链接显示几种:

http://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1

例如,你可以使用公共表表达式(CTE的)来生成序列,像这样:

WITH 
s1(n) AS -- 10 (10^1) 
    (   SELECT 1 
    UNION ALL SELECT 1 
    UNION ALL SELECT 1 
    UNION ALL SELECT 1 
    UNION ALL SELECT 1 
    UNION ALL SELECT 1 
    UNION ALL SELECT 1 
    UNION ALL SELECT 1 
    UNION ALL SELECT 1 
    UNION ALL SELECT 1 
) , 
s2(n) as (select 1 from s1 a cross join s1 b) , -- 10^2  100 
s3(n) as (select 1 FROM s1 a cross join s2 b) , -- 10^3  1,000 
s4(n) as (select 1 from s1 a cross join s3 b) , -- 10^4 10,000 
s5(n) as (select 1 from s1 a cross join s4 b) , -- 10^5 100,000 
s6(n) as (select 1 from s1 a cross join s5 b) , -- 10^6 1,000,000 
seq(n) as (select row_number() over (order by n) from s6) 
select * 
from dbo.some_table t 
join seq   s on s.n between 1 and len(t.flags) 
        and substring(t.flags,s.n,1) = '1'