2017-08-01 82 views
0

我對似乎應該非常簡單的東西感到困惑,但我現在太累了,現在不能再亂用了,所以我只是把它扔到這裏看看是否有人可以展示如何去做這件事。 我試圖做的是按照IDENTITY列(ID)按照組的順序和表中的值所屬的順序確定表的行。 我正在使用Microsoft SQL Server 2008 R2 Management Studio(v10.50.4000.0)。SQL Server:行按組排序和序列

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

我希望這是可以接受的,我要的話,你的各種失敗的嘗試(包括ROW_NUMBER,等級,DENSE_RANK,組等),我迄今爲止所做的......;我確信必須有一個相對簡單的解決方案,不會涉及單個操作,但我無法弄清楚。 注意:編輯值定義爲使zzz更清晰。 我希望這是有道理的,並提前感謝!

SOLUTION:

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; 

回答

1

如果我理解正確的,你的查詢會

;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 

演示鏈接:http://rextester.com/KGYT17255

+0

我忘了提,我使用Microsoft SQL Server 2008 R2管理Studio(v10.50.4000.0)所以功能LAG不適用於我。然而,一個快速搜索引導我到這(https://stackoverflow.com/questions/33283205/lag-lead-equivalent-with-grouping-sql-server-2008-r2),這可能會幫助我做這件作品的等價物。此外,順序需要按照ID(標識列)的順序,而不是Value。謝謝。 – Erg

+0

在sql server 2008中,您可以使用'APPLY'而不是'LAG'並按每個組的最小id來排序項目。我編輯了我的答案。 – TriV

+0

不幸的是,我正在使用古老的技術(2008 R2),所以ORDER BY不能用於聚合窗口函數(https://stackoverflow.com/questions/12686140/issue-with-window-function-in-mssql-2008 -R2)。但也許這將幫助我解決這一問題(https://stackoverflow.com/questions/38216962/sql-server-2008-r2-running-sum?rq=1)。再次感謝! – Erg