SQL根据时差创建行序列

时间:2017-03-03 18:10:42

标签: sql sql-server tsql gaps-and-islands

我正在尝试执行以下操作:我在系统中有用户活动的表,我想根据每个对象上每个活动的时间以及每个活动之间的时间来创建一系列活动到10秒,并给每个序列一个唯一的ID。

例如下表:

bundle update rails
该表上的

预期输出为:

  userID   ObjectID        Timestamp             
 ======== ========== ===================== 

       1         52   2016-05-01 19:10:01        
       1         52   2016-05-01 19:10:05        
       1         52   2016-05-01 19:10:07        
       1         52   2016-05-01 19:12:01        
       1         52   2016-05-01 19:12:04        
       2         54   2016-05-01 19:11:09        
       2         54   2016-05-01 19:11:19        
 ======== ========== ===================== == ==

我尝试使用row_number()和dense_rank()函数,但我没有成功使用10秒不同的条件。

2 个答案:

答案 0 :(得分:0)

<强> 1。按相同分钟排序

<script src="//js.maxmind.com/js/apis/geoip2/v2.1/geoip2.js" type="text/javascript"></script>
<script language="JavaScript">

var redirect = (function () {

    /* Get actual URL */
    var url = window.location.href; 

    /* This implements the actual redirection. */
    var redirectBrowser = function (site) {
        var uri = "https://www.example.com/" + site;
        window.location = uri;
    };

    /* These are the country codes for the countries we have sites for.
     * We will check to see if a visitor is coming from one of these countries.
     * If they are, we redirect them to the country-specific site. If not, we
     * redirect them to https://www.example.com/ */
    var sites = {
        "us": {"active": true, "target": "en-us"},
        "gb": {"active": true, "target": "en-gb"},
        "de": {"active": true, "target": "de"},
        "fr": {"active": true, "target": "fr"},
        "fi": {"active": true, "target": "fi"},
        "hu": {"active": true, "target": "hu"},
        "nl": {"active": true, "target": "nl"},
        "se": {"active": true, "target": "sv"}
    };
    var defaultSite = "";

    var onSuccess = function (geoipResponse) {
        /* There's no guarantee that a successful response object
         * has any particular property, so we need to code defensively. */
        if (!geoipResponse.country.iso_code) {
            redirectBrowser(defaultSite);
            return;
        }

        /* ISO country codes are in upper case. */
        var code = geoipResponse.country.iso_code.toLowerCase();

        if ( sites[code].active ) {
            redirectBrowser(sites[code].target);
        }
        else if ( url == defaultSite ) {
            return;
        }
        else {
            redirectBrowser(defaultSite);
        }

    };

    /* We don't really care what the error is, we'll send them
     * to the default site. */
    var onError = function (error) {
        redirectBrowser(defaultSite);
    };

    return function () {
        geoip2.country( onSuccess, onError );
    };
}());

redirect();

</script>
UserID      ObjectID    Timestamp               seq                  seqID
----------- ----------- ----------------------- -------------------- --------------------
1           52          2016-05-01 19:10:01.000 1                    1
1           52          2016-05-01 19:10:05.000 2                    1
1           52          2016-05-01 19:10:07.000 3                    1
2           54          2016-05-01 19:11:09.000 1                    2
2           54          2016-05-01 19:11:19.000 2                    2
1           52          2016-05-01 19:12:01.000 1                    3
1           52          2016-05-01 19:12:04.000 2                    3

<强> 2。我认为以下内容与您的说明相符。  @test与上面相同。

DECLARE @test TABLE(UserID INT,ObjectID INT,[Timestamp] DATETIME)
INSERT INTO @test
SELECT 1,52,CONVERT(DATETIME,'2016-05-01 19:10:01') UNION ALL   
SELECT 1,52,'2016-05-01 19:10:05' UNION ALL   
SELECT 1,52,'2016-05-01 19:10:07' UNION ALL   
SELECT 1,52,'2016-05-01 19:12:01' UNION ALL   
SELECT 1,52,'2016-05-01 19:12:04' UNION ALL   
SELECT 2,54,'2016-05-01 19:11:09' UNION ALL   
SELECT 2,54,'2016-05-01 19:11:19'

SELECT *
     , ROW_NUMBER()OVER(PARTITION BY DATEDIFF(MINUTE,0,Timestamp) ORDER BY [Timestamp]) AS seq   
     , DENSE_RANK()OVER(ORDER BY DATEDIFF(MINUTE,0,Timestamp)) as seqID
FROM @test
    UserID  ObjectID    Timestamp   SeqID   seq
1   1   52  01.05.2016 19:10:01 1   1
2   1   52  01.05.2016 19:10:05 1   2
3   1   52  01.05.2016 19:10:07 1   3
4   1   52  01.05.2016 19:12:01 2   1
5   1   52  01.05.2016 19:12:04 2   2
6   2   54  01.05.2016 19:11:09 3   1
7   2   54  01.05.2016 19:11:19 3   2

答案 1 :(得分:0)

Select *
Into   #Temp
From   ATable

Declare 
    @LoopCounter int = 1
    ,@TimeStamp1 datetime
    ,@TimeStamp2 datetime
    ,@Userid1 int
    ,@ObjectID1 int
    ,@Userid2 int
    ,@ObjectID2 int
    ,@Seq int
    ,@SeqID int


While @LoopCounter <= (Select Count(*) From #Temp)
Begin
    Select Top 1 
        @TimeStamp1 = TimeStamp 
        ,@Userid1 = UserId
        ,@ObjectID1 = ObjectID
        ,@Seq = Seq
        ,@SeqID = SeqID
    From #Temp
    Delete TOP 1 from #Temp
    Select Top 1 
        @TimeStamp2 = TimeStamp 
        ,@Userid2 = UserId
        ,@ObjectID2 = ObjectID

    from #Temp
    If(
        (@TimeStamp2 - @TimeStamp1) < 10
        and @Userid2 = @Userid1
        and @ObjectID2 = @ObjectID1
       )
    Begin
        Update 
            TableName
        Set 
            Seq = @Seq + 1
            ,SeqID = @SeqID
        Where 
            ObjectID = @ObjectID2
            and TimeStamp = TimeStamp2
    End

    Else
    Begin
        Update 
            TableName
        Set
            Seq = 1
            ,SeqID = @SeqID + 1
        Where
            ObjectID = @ObjectID2
            and TimeStamp = @TimeStamp2
    End

    @LoopCounter = @LoopCounter + 1

End

我认为应该这样做。如果我在代码中犯了任何错误,请告诉我。