2012-07-06 52 views
0

我試圖按順序將數據分組。說我有如下表:TSQL中的序列分組

| 1 | A | 
| 1 | A | 
| 1 | B | 
| 1 | B | 
| 1 | C | 
| 1 | B | 

我需要的SQL查詢輸出如下:

| 1 | A | 1 | 
| 1 | A | 1 | 
| 1 | B | 2 | 
| 1 | B | 2 | 
| 1 | C | 3 | 
| 1 | B | 4 | 

最後一列是每個組中增加一組號碼。重要的是要注意的是,第3,4和5行包含相同的數據,這些數據應該被分組爲2組而不是1.

+0

表格是否有唯一的標識符? – 2012-07-06 14:39:29

+2

沒有辦法可靠地做到這一點,除非有辦法區分表中的行的順序。如上所述,如果表是堆,然後添加聚集索引,則可能會/應該得到不同的結果。你需要提供更多信息。 – Sean 2012-07-06 14:44:18

+0

您的意思是第3,4和6行包含相同的數據。您絕不應該依賴於表格數據的存儲方式。 SQL不能像那樣工作。即使您確實知道SQL Server 2005始終以某種方式存儲數據,但這並不意味着2008年也會如此,或者2014年將會如此。如果你想要一個特定的訂單,那麼你需要在一列中設置它(例如可能使用時間戳) – Rodolfo 2012-07-06 14:57:06

回答

1

這會給你列上的排名。 但它不會給你1,2,3。 它會給你1,3,6等根據有多少在每個分組

select 
a, 
b, 
rank() over (order by a,b) 
from 
table1 

請參閱本SQLFiddle爲我的意思更清晰的想法:http://sqlfiddle.com/#!3/0f201/2/0

+0

不幸的是,這不會工作,因爲'b'不是他的'訂單'鍵(它可能是未定義的或缺失)。 – 2012-07-06 15:24:01

+0

好抓x-zero。我添加了一個似乎正在工作的順序。 – 2012-07-06 17:18:49

+0

不幸的是,他的鑰匙完全缺失。如果你仔細觀察他所期望的結果,你應該注意到他希望在'C'之後最後一個'B'會來' - 你指定的'ORDER BY'會導致它在'C'之前來臨。 OP似乎依賴於表中數據的順序,這至多是一種錯覺。 – 2012-07-06 17:59:44

1

正常的方式,你會做什麼你要的是DENSE_RANK函數:

select key, val, 
     dense_rank() over (order by key, val) 
from t 

然而,這並沒有解決分離的最後一個羣體的問題。

爲了解決這個問題,我必須假設有一個「id」列。 SQL中的表沒有排序,所以我需要排序。如果您使用的是SQL Server 2012,那麼您可以使用lag()函數來獲取所需內容。使用滯後,看是否關鍵,值對是連續的行相同:

with t1 as (
    select id, key, val, 
      (case when key = lead(key, 1) over (order by id) and 
         val = lead(val, 1) over (order by id) 
        then 1 
        else 0 
      end) as SameAsNext 
    from t 
    ) 
select id, key, val, 
     sum(SameAsNext) over (order by id) as GroupNum 
from t 

沒有SQL Server 2012中(其中有累計總和),你必須做一個自聯接,以確定每個初組:

select t.*, 
from t left outer join 
    t tprev 
    on t.id = t2.id + 1 and t.key = t2.key and t.val = t2.val 
where t2.id is null 

有了這個,使用分配組作爲最小ID的加入:

select t.id, t.key, t.val, 
     min(tgrp.id) as GroupId 
from t left outer join 
    (select t.*, 
     from t left outer join 
      t tprev 
      on t.id = t2.id + 1 and t.key = t2.key and t.val = t2.val 
     where t2.id is null 
    ) tgrp 
    on t.id >= tgrp.id 

如果你想這些是連續的號碼,然後把它們放在一個子查詢和使用DENSE_RANK() 。

1

對於MSSQL2008

假設你有一個SampleStatuses表:

Status Date 
A  2014-06-11 
A  2014-06-14 
B  2014-06-25 
B  2014-07-01 
A  2014-07-06 
A  2014-07-19 
B  2014-07-21 
B  2014-08-13 
C  2014-08-19 

你寫:

;with 
cte as (
    select ROW_NUMBER() over(order by Date) as RowNumber, 
    [Status], [Date] from SampleStatuses 
), 
cte2 as (
    select top 1 RowNumber, 1 as GroupNumber, [Status], [Date] from cte order by RowNumber 
    union all 
    select c1.RowNumber, 
     case when c2.Status <> c1.Status then c2.GroupNumber + 1 else c2.GroupNumber end as GroupNumber, c1.[Status], c1.[Date] 
    from cte2 c2 join cte c1 on c1.RowNumber = c2.RowNumber + 1  
) 
select * from cte2; 

將得到如下結果:

RowNumber GroupNumber Status Date 
1   1   A  2014-06-11 
2   1   A  2014-06-14 
3   2   B  2014-06-25 
4   2   B  2014-07-01 
5   3   A  2014-07-06 
6   3   A  2014-07-19 
7   4   B  2014-07-21 
8   4   B  2014-08-13 
9   5   C  2014-08-19