如何在 sql 中找到多行数据的子集?
我想在找到另一个字符串之前计算一个字符串(或数字)的出现次数,然后计算这个字符串在找到另一个字符串之前出现的次数。所有这些字符串都可以随机排列。
这就是我想要实现的目标:
我有一张表,其中有一列 ( columnx
),其中的数据如下:
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
这在 sql 中是否可能,或者仅仅编写一个小 C# 应用程序来做到这一点会更容易吗?
因为,根据您的评论,您可以添加一个明确定义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()
表达式替换为 just sortcolumn
。但是,我想,这一般不能保证。此外,您可能确实希望按时间戳而不是整数进行排序。
我不认为你可以用一个单一的选择来做到这一点。您可以使用 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 cnt
A 2
B 1
C 1
A 1
B 2