Sql 从第一个位置开始的顺序值的数目

Sql 从第一个位置开始的顺序值的数目,sql,sql-server,tsql,Sql,Sql Server,Tsql,我想知道从堆栈顶部开始的顺序颜色是什么以及有多少,但仅限于从顶部位置1开始的顺序颜色: 颜色位置 成堆 + red + 1 | red | 2 | red | 3 | blue | 4 Stack A | blue | 5 | red | 6 | red | 7 +---------+ | red | 1 Stack B +---------+ | blue

我想知道从堆栈顶部开始的顺序颜色是什么以及有多少,但仅限于从顶部位置1开始的顺序颜色:

颜色位置 成堆

+   red   +  1
|   red   |  2
|   red   |  3     
|   blue  |  4     Stack A
|   blue  |  5
|   red   |  6
|   red   |  7 
+---------+      


|   red   |  1     Stack B  
+---------+     
|   blue  |  1
|   red   |  2
|   red   |  3     Stack C
|   blue  |  4
+---------+      
下表:

Stack   Color    position
A       Red          1
A       Red          2
A       Red          3
A       blue         4
A       Blue         5
A       Red          6
A       Red          7
B       Red          1
C       blue         1
C       red          2
C       red          3
C       blue         4
结果我不会

Stack    Color      Quantity
A        Red        3
B        Red        1
C        Blue       1 
从堆栈A的顶部开始,我有3个连续的红色 从堆栈B的顶部开始,我有1个连续的红色 从堆栈C的顶部开始,我有一个连续的蓝色 短版

可用于查找每个堆栈的第一个颜色孤岛并将其聚合:

with islands as (
    select stack,color,position,
        position-dense_rank() over (partition by stack,color order by position) i
    from @table
)
select stack,color,count(*) as Count
from islands 
where i=0
group by stack,color
order by stack,color
这将产生:

stack   color   Count
A       Red     3
B       Red     1
C       blue    1
stack   color   position    Rank    Island
A       Red     1           1       0
A       Red     2           2       0
A       Red     3           3       0
A       blue    4           1       3
A       Blue    5           2       3
A       Red     6           4       2
A       Red     7           5       2
B       Red     1           1       0
C       blue    1           1       0
C       red     2           1       1
C       red     3           2       1
C       blue    4           2       2
解释

这被称为-如何在一组数据中找到相同或连续值的孤岛

这个位置在这里很有帮助,因为它改变了每个堆栈中的行为。我们现在需要的是在堆栈中按颜色查找孤岛。我们可以通过按堆栈和颜色计算稠密_秩来实现这一点

declare @table table (Stack varchar(2),Color varchar(10),Position int)

insert into @table(Stack   ,Color    ,position)
values
('A','Red'          ,1),
('A','Red'          ,2),
('A','Red'          ,3),
('A','blue'         ,4),
('A','Blue'         ,5),
('A','Red'          ,6),
('A','Red'          ,7),
('B','Red'          ,1),
('C','blue'         ,1),
('C','red'          ,2),
('C','red'          ,3),
('C','blue'         ,4)

select 
    stack,color,position,
    dense_rank() over (partition by stack,color order by position) as Rank
from @table
order by stack,position;
结果是:

stack   color   position    Rank
A       Red     1   1
A       Red     2   2
A       Red     3   3
A       blue    4   1
A       Blue    5   2
A       Red     6   4
A       Red     7   5
B       Red     1   1
C       blue    1   1
C       red     2   1
C       red     3   2
C       blue    4   2
在每种颜色中,密度等级和位置之间的差异是相同的。我们可以用它来确定岛屿:

select 
    stack,color,position,
    dense_rank() over (partition by stack,color order by position) as Rank,
    position-dense_rank() over (partition by stack,color order by position) as Island
from @table
order by stack,position
这将产生:

stack   color   Count
A       Red     3
B       Red     1
C       blue    1
stack   color   position    Rank    Island
A       Red     1           1       0
A       Red     2           2       0
A       Red     3           3       0
A       blue    4           1       3
A       Blue    5           2       3
A       Red     6           4       2
A       Red     7           5       2
B       Red     1           1       0
C       blue    1           1       0
C       red     2           1       1
C       red     3           2       1
C       blue    4           2       2
我们现在可以按堆栈、颜色和孤岛进行分组,以获得最终结果:

with x as (
    select stack,color,position,dense_rank() over (partition by stack,color order by position) r,
        position-dense_rank() over (partition by stack,color order by position) i
    from @table
)
select stack,color,count(*) as Count
from x 
where i=0
group by stack,color
order by stack,color

这不必被视为缺口和孤岛问题。我认为最简单的解决办法是:

select stack, first_color, count(*)
from (select t.*,
             min(case when color <> first_color then position end) over (partition by stack) as first_other_color_position
      from (select t.*, first_value(color) over (partition by stack order by position) as first_color
            from t
           ) t
     ) t
where first_other_color_position is null or position < first_other_color_position
group by stack, first_color
order by stack;
他是一把小提琴

逻辑很简单:

获取每个堆栈的第一种颜色。 获取不是该颜色的每一行的第一行位置。 使用该信息过滤和聚合数据。
请使用“我的编辑”作为示例来修改格式。@请停止弄乱问题文本和添加语法错误。没有人会将SQL Server与MySQL混为一谈,您已经标记了这一点。如果这个问题很难理解,你将得不到任何答案。现在理解你想要什么已经够难了。