如何根据行顺序计算dense_rank()

时间:2016-04-04 19:59:22

标签: sql-server sql-server-2008-r2

我遇到的问题看起来很简单,但我无法获得所需的输出。 我的样本数据如下: -

end_date_row    row_code
2010-06-30        12
2011-06-30        12
2012-06-30        12
2013-06-30        12
2014-06-30        12
2014-07-16        12
2014-12-31        18
2015-06-30        18
2015-07-06        18
2015-11-17        12
NULL              18

我希望输出为 -

end_date_row    row_code    rn
2010-06-30         12        1
2011-06-30         12        1
2012-06-30         12        1
2013-06-30         12        1
2014-06-30         12        1
2014-07-16         12        1
2014-12-31         18        2
2015-06-30         18        2
2015-07-06         18        2
2015-11-17         12        3
NULL               18        3

下面的代码让我接近但我仍然无法得到确切的输出。

select end_date_row,row_code,rn1
from
(
select end_date_row,row_code,row_number() over (order by (select 1)) as rn, row_number() over (order by (select 1)) - row_number() over (partition by row_code order by (end_date_row)) as rn1
from a
) as abc
order by rn

上面代码的输出是 -

end_date_row  row_code  rn1
2010-06-30  12  0
2011-06-30  12  0
2012-06-30  12  0
2013-06-30  12  0
2014-06-30  12  0
2014-07-16  12  0
2014-12-31  18  5
2015-06-30  18  5
2015-07-06  18  5
2015-11-17  12  3
 NULL       18  10

我不能使用超前/滞后功能,因为我使用的是sql server 2008r2。我们可以在没有递归cte或while循环的情况下解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

您可以使用以下查询:

SELECT end_date_row, row_code, 
       SUM(COALESCE(flag, 0)) OVER 
       (ORDER BY COALESCE(end_date_row, '9999-12-31')) + 1
FROM (
  SELECT end_date_row, row_code,
         CASE WHEN row_code <> 
                   LAG(row_code) OVER 
                   (ORDER BY COALESCE(end_date_row, '9999-12-31')) 
            THEN 1 END AS flag       
  FROM a) AS t

Demo here

如果您希望将NULL字段中的结尾end_date_row值视为&#39;则不会更改&#39;然后使用这个:

SELECT end_date_row, row_code, 
       SUM(COALESCE(flag, 0)) OVER 
       (ORDER BY COALESCE(end_date_row, '9999-12-31')) + 1
FROM (
  SELECT end_date_row, row_code,
         CASE WHEN end_date_row IS NOT NULL AND
                   row_code <> 
                   LAG(row_code) OVER 
                   (ORDER BY COALESCE(end_date_row, '9999-12-31')) 
            THEN 1 END AS flag       
  FROM a) AS t

Demo here

在SQL-Server 2008中,您可以使用:

SELECT end_date_row, row_code, 
       DENSE_RANK() OVER (ORDER BY COALESCE(group_date, '9999-12-31'))
FROM (
  SELECT end_date_row, row_code, 
         MIN(end_date_row) OVER (PARTITION BY grp) AS group_date
  FROM (
    SELECT end_date_row, row_code,
         ROW_NUMBER() OVER (ORDER BY COALESCE(end_date_row, '9999-12-31')) -
         ROW_NUMBER() OVER (PARTITION BY row_code 
                            ORDER BY COALESCE(end_date_row, '9999-12-31')) AS grp
    FROM a) AS t) AS s

Demo here

答案 1 :(得分:0)

不确定,但这可能会这样做

select end_date_row, row_code 
     , dense_rank() over (order by rnA - rnP) as rn
from ( select end_date_row, row_code 
            , row_number() over (                      order by end_date_row) as rnA
            , row_number() over (partition by row_code order by end_date_row) as rnP
         from a 
     ) tt