4

SQLで複数の行にまたがるデータのサブセットを見つけるにはどうすればよいですか?

別の文字列が見つかる前に文字列 (または数値) の出現回数をカウントし、別の文字列が見つかる前にこの文字列が出現する回数をカウントしたいと考えています。これらの文字列はすべてランダムな順序にすることができます。

これは私が達成したいことです:

columnx次のようなデータを含む1 つの列 ( ) を持つ 1 つのテーブルがあります。

A
A
B
C
A
B
B

クエリの結果は次のようになります。

2 A
1 B
1 C
1 A
2 B

これはSQLでも可能ですか、それともこれを行うために小さなC#アプリを書く方が簡単でしょうか?

4

3 に答える 3

3

コメントに従って、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)
;

このメソッドはSQL Fiddle で動作していることがわかります。

sortcolumnがギャップがないことが保証されている自動インクリメント整数列である場合、最初の式を単に に置き換えることができROW_NUMBER()ますsortcolumn。しかし、それは一般的には保証できないと思います。さらに、整数ではなくタイムスタンプでソートしたい場合もあります。

于 2012-04-05T05:14:40.453 に答える
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
于 2012-04-04T10:31:57.887 に答える
1

単一の選択でそれを行うことができるとは思わない。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
于 2012-04-04T09:34:43.843 に答える