一旦值改变,就在分区内重新开始编号

时间:2017-03-30 08:12:36

标签: sql-server partitioning ranking row-number

我正在努力解决一个非常简单(我认为)的话题,我无法继续这样做。

示例数据:

|ready_signal|timestamp          |
|4           |2017-03-17 17:58:25|
|4           |2017-03-17 17:58:24|
|4           |2017-03-17 17:58:23|
|0           |2017-03-17 17:58:22|
|0           |2017-03-17 17:58:21|
|0           |2017-03-17 17:58:19|
|4           |2017-03-17 17:58:18|
|4           |2017-03-17 17:58:15|
|0           |2017-03-17 17:58:10|
|0           |2017-03-17 17:58:09|
|0           |2017-03-17 17:58:04|
|4           |2017-03-17 17:58:03|

现在我想要实现的是,在每个ready_signal更改中获得时间戳的最大值。 所以结果应该是这样的:

|ready_signal|timestamp          |
|4           |2017-03-17 17:58:25|
|0           |2017-03-17 17:58:22|
|4           |2017-03-17 17:58:18|
|0           |2017-03-17 17:58:10|
|4           |2017-03-17 17:58:09|

我尝试使用ROW_NUMBER等分区功能,但没有成功。我无法对这些列进行分区。对ready_signal进行分区,只返回两个值(并在分区中使用ORDER BY)。

我认为,有人肯定有同样的问题。就像,我需要一个唯一的分区号,但每次ready_signal值都会改变。

抱歉,不发布示例代码。 这就是我在试验的内容:

SELECT ready, 
    timestamp,
    ROW_NUMBER() OVER(PARTITION BY ready ORDER BY timestamp DESC) AS readyTime
FROM bubu
ORDER BY timestamp DESC

我还试图获取一些最大值:

SELECT ready, 
    timestamp,
    ROW_NUMBER() OVER(PARTITION BY ready ORDER BY timestamp DESC) AS readyTime
FROM bubu
ORDER BY timestamp DESC

2 个答案:

答案 0 :(得分:1)

这很接近但是我已经对这个问题发表了评论 - 因为时间戳不是唯一的,所以可以获得不同的结果集。在这种情况下,我经常0获取另一个2017-03-17 17:58:09行,因为可以想象其中一行发生在4之前。

无论如何,写这个的方法是你要选择没有后继者的行或者后继者对ready_state具有不同值的行。一旦你重新陈述了这样的问题,代码就会自己写出来:

declare @t table (ready_signal int,timestamp datetime)
insert into @t(ready_signal,timestamp) values
(4,'2017-03-17T17:58:25'),
(4,'2017-03-17T17:58:24'),
(4,'2017-03-17T17:58:23'),
(0,'2017-03-17T17:58:22'),
(0,'2017-03-17T17:58:21'),
(0,'2017-03-17T17:58:19'),
(4,'2017-03-17T17:58:18'),
(4,'2017-03-17T17:58:15'),
(0,'2017-03-17T17:58:10'),
(0,'2017-03-17T17:58:09'),
(0,'2017-03-17T17:58:09'),
(4,'2017-03-17T17:58:09')

;With Numbered as (
    select ready_signal,timestamp,
        ROW_NUMBER() OVER (ORDER BY timestamp) as rn
    from @t
)
select
    t1.ready_signal,t1.timestamp
from
    Numbered t1
        left join
    Numbered t2
        on
            t1.rn = t2.rn - 1
where
    t2.rn is null or --No successor
    t2.ready_signal != t1.ready_signal --Successor different

结果:

ready_signal timestamp
------------ -----------------------
0            2017-03-17 17:58:09.000
4            2017-03-17 17:58:09.000
0            2017-03-17 17:58:10.000
4            2017-03-17 17:58:18.000
0            2017-03-17 17:58:22.000
4            2017-03-17 17:58:25.000

(如果结果集的顺序对您很重要,您可以添加一个明确的ORDER BY

答案 1 :(得分:0)

尝试以下查询,这将为您提供问题中所述的确切所需输出。

DECLARE @SAMPLEDATA TABLE(READYSIGNAL INT,TIMESTAMPP DATETIME)
INSERT INTO @SAMPLEDATA VALUES
(4,'2017-03-17 17:58:25'),
(4,'2017-03-17 17:58:24'),
(4,'2017-03-17 17:58:23'),
(0,'2017-03-17 17:58:22'),
(0,'2017-03-17 17:58:21'),
(0,'2017-03-17 17:58:19'),
(4,'2017-03-17 17:58:18'),
(4,'2017-03-17 17:58:15'),
(0,'2017-03-17 17:58:10'),
(0,'2017-03-17 17:58:09'),
(0,'2017-03-17 17:58:09'),
(4,'2017-03-17 17:58:09')
;WITH SAMPLEDATA
AS
(
SELECT *,1 COL FROM (SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 100))SNO,*
 FROM @SAMPLEDATA)T WHERE SNO=1
UNION ALL
SELECT T2.SNO,T2.READYSIGNAL,T2.TIMESTAMPP,
    CASE WHEN T1.READYSIGNAL=T2.READYSIGNAL THEN T1.COL ELSE T1.COL+1 END
        FROM SAMPLEDATA T1 JOIN (SELECT ROW_NUMBER()OVER(ORDER BY (SELECT     100))SNO,*
 FROM @SAMPLEDATA) T2 ON T1.SNO=T2.SNO-1
)
SELECT READYSIGNAL,TIMESTAMPP FROM
    (SELECT READYSIGNAL,MAX(TIMESTAMPP)TIMESTAMPP,MAX(SNO)SNO FROM     SAMPLEDATA     GROUP BY COL,READYSIGNAL)RESULT ORDER BY SNO 

<强>输出

------------------------------------------
--READYSIGNAL   TIMESTAMPP
------------------------------------------
    4           2017-03-17 17:58:25.000
    0           2017-03-17 17:58:22.000
    4           2017-03-17 17:58:18.000
    0           2017-03-17 17:58:10.000
    4           2017-03-17 17:58:09.000
-----------------------------------------