Sql server SQL Server:按组和顺序的行排序

Sql server SQL Server:按组和顺序的行排序,sql-server,sql-server-2008-r2,Sql Server,Sql Server 2008 R2,我被一些看起来应该很简单的事情所困扰,但我现在已经太累了,不能再去搞它了,所以我把这个扔到这里,看看是否有人能告诉我怎么做。 我试图做的是根据组、序列以及表中的值所属序列的顺序(按标识列ID排序)来标识表中的行。 我使用的是Microsoft SQL Server 2008 R2 Management Studio v10.50.4000.0 declare @X table ( ID int identity, Value varchar(20) ); insert @X select 'a

我被一些看起来应该很简单的事情所困扰,但我现在已经太累了,不能再去搞它了,所以我把这个扔到这里,看看是否有人能告诉我怎么做。 我试图做的是根据组、序列以及表中的值所属序列的顺序(按标识列ID排序)来标识表中的行。 我使用的是Microsoft SQL Server 2008 R2 Management Studio v10.50.4000.0

declare @X table (
ID int identity,
Value varchar(20)
);

insert @X
select 'abc'
union all
select 'zzz' --def
union all
select 'abc'
union all
select 'abc'
union all
select 'xyz'
union all
select 'abc'
union all
select 'abc';

select * from @X;
最终结果应该如下所示:

/*
*GO-GroupOrder; SO-SequenceOrder; GSO-GroupSequenceOrder
ID  Value   GO  SO  GSO
1   abc     1   1   1
2   zzz     2   2   1 --def
3   abc     1   3   2
4   abc     1   3   2
5   xyz     3   4   1
6   abc     1   5   3
7   abc     1   5   3
*/
我希望这是可以接受的,我将为您省去各种失败的尝试,包括排号、排名、密集排名、分组等等,我到目前为止已经做了。。。;我确信一定有一个相对简单的解决方案,它只涉及整个集合中的一个操作,但我无法理解。注意:编辑了def到zzz的值,以使请求的顺序更加清晰。 我希望这是有意义的,并提前表示感谢

解决方案:

with
    cte1 as (
        select
            x.ID,
            x.Value,
            oX.ValuePrevious
        from @X as x
        outer apply (
            select
                top 1
                    oX.Value as ValuePrevious
            from @X as oX
            where x.ID > oX.ID
            order by oX.ID desc
            ) as oX
        ),
    cte2 as (
        select
            min(ID) as IDMin,
            Value
        from @x
        group by Value
        ),
    cte3 as (
        select
            cte1.ID,
            cte1.Value,
            dense_rank() over (order by cte2.IDMin) as [GO],
            cCTE1.SO
        from cte1
        cross apply (
            select
                sum(case 
                    when 1 <> 1
                        or cCTE1.ValuePrevious != cCTE1.[Value]
                        or cCTE1.ValuePrevious is NULL
                    then 1
                    else 0
                    end) as SO
            from cte1 as cCTE1
            where cte1.ID >= cCTE1.ID
            ) as cCTE1
        join cte2
            on cte2.Value = cte1.Value
        )
    select
        ID,
        Value,
        [GO],
        SO,
        dense_rank() over (partition by [GO] order by SO) as [GSO]
    from cte3 order by ID;

如果我理解正确,您的问题将是

 ;WITH temp AS
(
    select  x.ID,
            x.[Value], 
            pre.PreviousValue      
    from @X x
    OUTER APPLY
    (
        SELECT  TOP 1 
                x2.[Value] AS PreviousValue
        FROM @X x2
        WHERE x2.ID < x.ID
        ORDER BY x2.ID DESC
    ) pre
),
temp1 AS
(
    SELECT x2.[Value], min(x2.ID) AS MinGrId
    FROM @X x2
    GROUP BY x2.[Value]
),
temp2 AS
(
select  t.*,
       SUM(CASE 
             WHEN t.PreviousValue != t.[Value] OR t.PreviousValue IS null THEN 1 
             ELSE 0
          END) OVER(ORDER BY t.ID) AS [SO],
        dense_rank() OVER(ORDER BY t1.MinGrId) AS [GO]
from temp t    
INNER JOIN temp1 t1 ON t.[Value] = t1.[Value]
)
SELECT t.ID, t.[Value], t.[GO], t.SO,
      dense_rank() OVER(PARTITION BY t.[GO] ORDER BY t.SO) AS GSO
FROM temp2 t
ORDER BY t.ID

演示链接:

我忘了提到我使用的是Microsoft SQL Server 2008 R2 Management Studio v10.50.4000.0,因此函数滞后对我不可用。然而,一个快速的搜索让我找到了这一点,这可能会帮助我为那篇文章做同样的事情。此外,排序需要按标识列的ID顺序,而不是按值顺序。谢谢。在SQLServer2008中,您可以使用APPLY而不是LAG,并按每个组的最小id排序项目。我编辑了我的答案。不幸的是,我使用的是古代科技2008 R2,因此ORDER BY不能用于聚合窗口函数。但也许这能帮我修好那块。再次感谢!