2012-07-06 51 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