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

时间:2019-06-14 08:20:08

标签: 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   |  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个连续的RED
  • 我从堆栈B的顶部开始有1个连续的RED
  • 我从堆栈C的顶部开始有1个连续的蓝色

2 个答案:

答案 0 :(得分:1)

简短版本

DENSE_RANK可用于查找每叠颜色的第一个“岛”并将其聚合:

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

说明

这称为Islands problem-如何在一组数据中查找具有相同或连续值的“岛”。

Position在这里有帮助,因为它可以更改每个`stack中的行为。我们现在需要的是通过堆栈中的颜色 查找孤岛。我们可以通过按堆栈和颜色计算DENSE_RANK来做到这一点。

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   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

答案 1 :(得分:0)

这不必被视为是一个空白问题。我认为最简单的解决方案是:

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;

Here是db <>小提琴。

逻辑很简单:

  • 获取每个堆栈的第一种颜色。
  • 获取每种不是该颜色的第一行的位置。
  • 使用该信息来筛选和汇总数据。