2014-11-05 2 views
0

관련 답변을 광범위하게 검색했지만 수행해야 할 작업을 모두 충족하지 못했습니다. 우리의 목적을 위해SQL Server의 이진 문자열 파싱/인덱싱

나는 50 문자 이진 문자열을 열 수 있습니다. 우리 데이터베이스에서는 실제로 수백 자 길이입니다.

데이터베이스에있는 고유 항목 ID마다 하나의 문자열이 있습니다. 각 '1'의 위치는 특정 조건을 true로 표시하고 '0'은 거짓으로 표시하므로 1과 0의 색인 위치가 매우 중요합니다. 대부분은 1이 어디에 있는지 신경이 쓰입니다. 내가 어떤 데이터베이스를 업데이트하고 있지 않다

, 그래서 내가 먼저 시도하고 각각의 문자열을 통해보고 1의 위치 목록을 생성하는 루프를 만들기로 결정했다.

1, 7, 12, 13, 20, 50 

그러나 루프가 '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의 루프가 정상적으로 문자열의 끝 부분에 도달 할 때 휴식 기준을 얼마나 만족시키는 지 잘 모르겠습니다.

루프 폭탄에 대한 간단한 해결책이 있습니까? 또한 첫 번째 루프에서 반복해야합니까? 장소?

나는 등 다른 분석 방법, 노조 가입, 색인, 시도,하지만 난 내가 필요 확실히 어떤 한 조합을 찾을 수 없습니다 상황이 매우 구체적인 세트를 부여했다. 위의 코드는 지금까지 내가 가지고있는 최고입니다.

은 내가 특별히 출력으로 목록을 쉼표로 구분이 필요하지 않습니다,하지만 난 문자열 내의 모든 일의의의 위치를 ​​알아야합니다. 1의 값은 다양하지만 문자열 크기는 항상 같습니다.

이 유래 내 처음으로 게시,하지만 난이 답변을 여러 번 사용했습니다. 나는 관련 정보를 명확하게 질문하고자한다. 내가 도울 수있는 일이 있다면, 나는 어떤 요구라도 이행하려고 노력할 것이다.

답변

0

어떻게 이런 일에 while 조건을 변경하는 방법에 대한?

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

이 필요하지 않는 문제를 해결하기위한 좋은 작품이 링크는 몇 가지 보여줍니다 문자열 끝에는 1이지만, 문자열 내에 1이 없으면 폭탄을 넣을 것입니다. 그게 전부 좋은 걸까요? 아마도 성명서일까요? –

+0

@Muffin_Cup. . . 이 경우 "폭탄"은 어떻게됩니까? 그럴 경우'@list'는 비어 있습니다. –

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이 발견되지 않으면 break가 루프에서 빠져 나와 문자열에서 from을 다시 시작하지 못하게합니다. –

+0

이 루프도 잘 작동하지만 문자열에 1이 없으면 (모두 0) 폭탄이 있습니다.이 문제에 대한 좋은 해결책이 있습니까? –

+0

루프 바로 전에 어떤 1의 존재에 대한 간단한 점검을하십시오. (charindex ('1', @binarystring, @position)> 0 - while 루프 넣기 –

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 , 
) 

같은이 다음 flags 열의 각 1

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' 

을, 당신은을 포함하는 행을 얻을 것이다 소스 테이블 ID 열의 ID와 1이있는 위치는 flags입니다.

이러한 시퀀스를 생성하는 데는 여러 가지 기술이 있습니다.

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'