多行上的T-Sql计数字符串序列

多行上的T-Sql计数字符串序列,sql,gaps-and-islands,Sql,Gaps And Islands,如何在sql中找到多行数据的子集 我想计算一个或多个字符串在找到另一个字符串之前出现的次数,然后计算这个字符串在找到另一个字符串之前出现的次数。 所有这些字符串可以是随机顺序 这就是我想要实现的目标: 我有一个表,其中有一列columnx,数据如下: A A B C A B B 2 A 1 B 1 C 1 A 2 B 我希望查询的结果如下所示: A A B C A B B 2 A 1 B 1 C 1 A 2 B 这在sql中是可能的,还是仅仅编写一个C应用程序就可以更容易地做到这一点呢?

如何在sql中找到多行数据的子集

我想计算一个或多个字符串在找到另一个字符串之前出现的次数,然后计算这个字符串在找到另一个字符串之前出现的次数。 所有这些字符串可以是随机顺序

这就是我想要实现的目标:

我有一个表,其中有一列columnx,数据如下:

A
A
B
C
A
B
B
2 A
1 B
1 C
1 A
2 B
我希望查询的结果如下所示:

A
A
B
C
A
B
B
2 A
1 B
1 C
1 A
2 B

这在sql中是可能的,还是仅仅编写一个C应用程序就可以更容易地做到这一点呢?

我认为你不可能只用一次选择就能做到。 您可以使用AdventureWorks光标:

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 @nr=@nr+1
        set @myLastString=@myString
    end else begin
        insert into @temp_result values (@myLastString, @nr)
        set @myLastString=@myString
        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
结果:

A   2
B   1
C   1
A   1
B   2
试试这个:

;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值的顺序,因此,如果您使用的SQL产品支持CTE和排名函数,您可以尝试以下查询:

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)
;
你可以在工作中看到这种方法


如果sortcolumn是一个保证没有间隙的自动递增整数列,则可以仅用sortcolumn替换第一行\u数表达式。但是,我想,总的来说,这是不能保证的。此外,您可能确实希望根据时间戳而不是整数进行排序。

必须有一列或一组列来确定顺序。默认情况下,表中的行是无序的。必须有另一列或多列可用于确定值的正确顺序。SQL从不保证订单数据在没有其他数据明确确定订单的情况下被处理、存储或显示。例如:按排序顺序从表中选择columnx。您是否有一个类似sort_order的列,您可以根据它对数据进行排序?[另外,您使用的是什么版本的SQL Server/SyBase/etc?]我可以添加一个自动递增列或一个日期列来进行排序。这似乎非常有效,我将尽快在实际数据上进行尝试。此查询似乎也很有效,正如预期的那样,如果您有近200万行,所有这些查询都会花费很长时间: