2014-11-05 98 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'