如何在sql中找到多行数据的子集?
我想在找到另一个字符串之前计算字符串(或数字)的出现次数,然后计算此字符串在找到另一个字符串之前出现的次数。 所有这些字符串都可以按随机顺序排列。
这就是我想要实现的目标:
我有一个包含一列(columnx
)的表,其数据如下:
A
A
B
C
A
B
B
我想从查询中得到的结果应该是这样的:
2 A
1 B
1 C
1 A
2 B
这在sql中是否可行?或者只是编写一个小的C#应用程序来做这件事会更容易吗?
答案 0 :(得分: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)
;
您可以在工作on SQL Fiddle中看到该方法。
如果sortcolumn
是一个保证没有间隙的自动增量整数列,则可以用ROW_NUMBER()
替换第一个sortcolumn
表达式。但是,我想,这一般无法得到保证。此外,您可能确实想要对时间戳进行排序而不是整数。
答案 1 :(得分: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
答案 2 :(得分: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