2012-04-04 3 views
4

sql에서 여러 행에 걸쳐 데이터 하위 집합을 어떻게 찾을 수 있습니까?여러 행에 걸쳐 T-SQL 계산 문자열 시퀀스

다른 문자열이 발견되기 전에 문자열 (또는 숫자)의 발생 횟수를 계산하고 다른 문자열이 발견되기 전에이 문자열이 발생한 횟수를 계산하고 싶습니다. 이 모든 문자열은 임의의 순서 일 수 있습니다.

내가 달성하고자하는 것입니다 :

을 내가 가진이 같은 데이터를 하나의 열 (columnx)과 한 테이블 :

A 
A 
B 
C 
A 
B 
B 

I는 다음과 같이해야한다 쿼리에서 원하는 결과 :

2 A 
1 B 
1 C 
1 A 
2 B 

는 SQL이 가능하다조차 또는이 작업을 수행하려면 약간의 C# 응용 프로그램을 작성하는 단지 쉬울 것?

+3

시퀀스를 결정하는 열 (또는 열 집합)이 있어야합니다. 표의 행은 기본적으로 정렬되지 않습니다. –

+3

값의 올바른 순서를 결정하는 데 사용할 수있는 다른 열이 있어야합니다. SQL * never * *** 보장 *** 주문 데이터는 다른 데이터없이 처리, 저장 또는 표시되므로 명시 적으로 해당 순서를 결정할 수 있습니다. 예를 들면 :'SELECT columnx FROM yourTable ORDER BY sort_order'. 데이터를 정렬 할 수있는'sort_order'와 같은 컬럼이 있습니까? * [또한, 어떤 버전의 SQL Server/SyBase/etc를 사용하고 있습니까?] * – MatBailie

+0

주문에 대해 자동 증분 열 또는 날짜 열을 추가 할 수 있습니다. – Thomas

답변

1

나는 하나의 선택으로 할 수 있다고 생각하지 않는다.

create table my_Strings 
(
my_string varchar(50) 
) 


insert into my_strings values('A'),('A'),('B'),('C'),('A'),('B'),('B') -- this method will only work on SQL Server 2008 

--select my_String from my_strings 

declare @temp_result table(
string varchar(50), 
nr int) 

declare @myString varchar(50) 
declare @myLastString varchar(50) 
declare @nr int 

set @myLastString='A' --set this with the value of your FIRST string on the table 
set @nr=0 

DECLARE string_cursor CURSOR 
FOR 
SELECT my_string as aux_column FROM my_strings 

OPEN string_cursor 
FETCH NEXT FROM string_cursor into @myString 
WHILE @@FETCH_STATUS = 0 BEGIN 
    if (@myString = @myLastString) begin 
     set @[email protected]+1 
     set @[email protected] 
    end else begin 
     insert into @temp_result values (@myLastString, @nr) 
     set @[email protected] 
     set @nr=1 
    end 
    FETCH NEXT FROM string_cursor into @myString 
END 
insert into @temp_result values (@myLastString, @nr) 
CLOSE string_cursor; 
DEALLOCATE string_cursor; 

select * from @temp_result 

결과 : 당신의 AdventureWorks 커서를 사용할 수 있습니다

A 2 
B 1 
C 1 
A 1 
B 2 
+0

이것은 완벽하게 작동하는 것처럼 보입니다. 최대한 빨리 데이터를 제공합니다. – Thomas

1

보십시오이 :

;with sample as (
    select 'A' as columnx 
    union all 
    select 'A' 
    union all 
    select 'B' 
    union all 
    select 'C' 
    union all 
    select 'A' 
    union all 
    select 'B' 
    union all 
    select 'B' 
), data 
as (
select columnx, 
    Row_Number() over(order by (select 0)) id 
    from sample 
) , CTE as (

     select * , 
    Row_Number() over(order by (select 0)) rno from data 

) , result as (

    SELECT d.* 
       , (SELECT MAX(ID) 
        FROM CTE c 
        WHERE NOT EXISTS (SELECT * FROM CTE 
             WHERE rno = c.rno-1 and columnx = c.columnx) 
          AND c.ID <= d.ID) AS g 
     FROM data d 
) 



SELECT columnx, 
     COUNT(1) cnt 
FROM result 
GROUP BY columnx, 
      g 

결과 :

columnx cnt 
A   2 
B   1 
C   1 
A   1 
B   2 
+0

이 쿼리는 거의 2 백만 행이 있으면 예상대로 모든 쿼리가 영원히 걸릴 것으로 예상대로 잘 작동하는 것 같다 :) – Thomas

3

, 이후 귀하의 의견에 따라, 당신 열을 추가 할 수 있습니다.

WITH marked AS (
    SELECT 
    columnx, 
    sortcolumn, 
    grp = ROW_NUMBER() OVER (     ORDER BY sortcolumn) 
     - ROW_NUMBER() OVER (PARTITION BY columnx ORDER BY sortcolumn) 
    FROM data 
) 
SELECT 
    columnx, 
    COUNT(*) 
FROM marked 
GROUP BY 
    columnx, 
    grp 
ORDER BY 
    MIN(sortcolumn) 
; 

당신은 작업 on SQL Fiddle의 방법을 볼 수 있습니다 즉 명확하게되는 columnx 값이 가고, 당신은 다음과 같은 쿼리를 시도 할 수 순서를 정의 할 것이다 (당신이 지원의 열팽창 계수를 사용하여 기능을 순위에있는 SQL 제품을 제공).

sortcolumn이 틈이없는 자동 증가 정수 열인 경우 첫 번째 ROW_NUMBER() 표현식을 sortcolumn으로 바꿀 수 있습니다. 그러나 일반적으로 보장 할 수는 없습니다. 게다가 정수 대신 타임 스탬프를 정렬하려고 할 수도 있습니다.

관련 문제