简体   繁体   中英

SQL Server, Getting records from random date where not started with specific column value

I want to get data from one of my tables which has EventTime column that keeps DateTime and EventType column which has 1 and 5 as value.

The result data should return sum of duration times between two event types group by NetworkNode and also should return number of changing EventType from 1 to 5 group by NetworkNode.

The structure of table is as below and cannot going to be changed:

CREATE TABLE [dbo].[Events]
(
    [EventID] [INT] NOT NULL,
    [EventTime] [DATETIME] NULL,
    [NetworkNode] [INT] NULL,
    [EventType] [SMALLINT] NULL,
    [Message] [NVARCHAR](MAX) NULL,
    [NetObjectType] [VARCHAR](10) NULL,

    CONSTRAINT [PK_Events] 
        PRIMARY KEY NONCLUSTERED ([EventID] ASC)
                    WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, 
                          ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

And the sample data inserted in table is as below:

样本数据

The 1 value means connection has timed out and 5 value means connection has responded again.

So it may have more than one rows with 1 value (EventType) continuously till 5 value shows up.

The filter for getting data is EventTime. I have to get data from , for example , 30 days before, so while I try to filter by 30 days before current day, the first row of result may return 5 as EventType value and it makes the duration minus.

Is there any way to remove the first row of query result with condition of EventType value equals to 5?

Just for understanding:

  • If result(0)['EventType'] = 5 remove result(0)

Also, if more than one record have (EventType = 1) continuously before a record with (EventType = 5), all duplicated records with (EventType = 1) except last must be ignored due to get the correct duration between (EventType = 1) and (EventType = 5).

Is it possible only using SQL server query? Or it needs to use some programming language too? Such as C# and LINQ, etc.

I understand your requirement as a variant of the gaps-and-island problem: basically, you want to group together consecutive records that have the same netword node and status.

Here is one approach that will give you the first and last EventID of each series of records having the same NetworkNode and EventType , along with the number of events in the series, the start and end EventTime , and their difference, in minutes.

select 
    NetworkNode,
    EventType,
    min(EventID) FirstEventID,
    max(EventID) LastEventID,
    count(*) EventCount
    min(EventTime) FirstEventTime,
    max(EventTime) LastEventTime,
    datediff(minute, min(EventTime), max(EventTime)) Duration
from (
    select
        e.*,
        row_number() over(partition by NetworkNode order by EventTime) rn1,
        row_number() over(partition by NetworkNode, EventType order by EventTime) rn2
    from events e
) e
group by 
    NetworkNode, 
    EventType, 
    rn1 - rn2

@Larnu sorry for bad formatting in my question.

Here is 10 rows from data inserted in table:

EventID EventTime                   NetworkNode     EventType
1       2019-11-10 15:34:00.000     3               1
2       2019-11-10 15:46:00.000     3               5
3       2019-11-10 16:08:00.000     5               1
4       2019-11-10 16:28:00.000     5               5
5       2019-11-10 16:36:00.000     5               1
6       2019-11-10 16:46:00.000     5               5
7       2019-11-11 10:18:00.000     9               1
8       2019-11-11 10:26:00.000     9               5
9       2019-11-11 13:45:00.000     9               1
10      2019-11-11 13:51:00.000     9               5

I tried to get result by below query and it works fine, but while I want to Group rows by NetworkNode , an error will rise as below:

Column 'Events.EventID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

select
   t1.EventID,
   t1.EventTime,
   t2.EventTime,
   t1.NetworkNode,
   t1.EventType,
   t2.EventType,
   DATEDIFF(minute , t1.EventTime, t2.EventTime) as Duration 
from
   (
      select
         *,
         ROW_NUMBER() OVER(
      Order by
         eventid) as CNumber 
      from
         Events 
      where
         EventTime >= DATEADD(day, - 30, GETDATE()) 
         and NetObjectType = 'N'
         And EventType = 1
   )
   as t1 
   inner join
      (
         select
            *,
            ROW_NUMBER() OVER( Order by eventid) as CNumber 
         from
            Events 
         where
            EventTime >= DATEADD(day, - 30, GETDATE()) 
            and NetObjectType = 'N' 
            And EventType = 5
      )
      as t2 
      on t1.CNumber = t2.CNumber AND t1.NetworkNode = t2.NetworkNode

With many thanks to @GMB, here is the query and its result which is too much near to what I expected but have some problems that I know it's because of bad transferring the concept by me.

Query :

select 
    NetworkNode,
    EventType,
    min(EventID) FirstEventID,
    max(EventID) LastEventID,
    count(*) EventCount
    min(EventTime) FirstEventTime,
    max(EventTime) LastEventTime,
    datediff(minute, min(EventTime), max(EventTime)) Duration
from (
    select
        e.*,
        row_number() over(partition by NetworkNode order by EventTime) rn1,
        row_number() over(partition by NetworkNode, EventType order by EventTime) rn2
    from events e
) e
group by 
    NetworkNode, 
    EventType, 
    rn1 - rn2

Result :

Node    Event    FirstEvent  LastEvent  EventCount  FirstEventTime          LastEventTime           Duration
24      1        13191615    13191615   1           2019-11-16 22:12:14.000 2019-11-16 22:12:14.000 0
24      5        13191653    13191653   1           2019-11-16 22:14:35.000 2019-11-16 22:14:35.000 0
25      1        12072600    12072600   1           2019-10-22 12:53:34.000 2019-10-22 12:53:34.000 0
25      5        12074438    12074438   1           2019-10-22 14:19:48.000 2019-10-22 14:19:48.000 0
26      1        12740974    12741155   4           2019-11-02 12:47:41.000 2019-11-02 12:47:53.000 12
26      1        12741302    13039438   2           2019-11-02 12:48:07.000 2019-11-10 15:03:00.000 699293
26      5        12741301    12741301   1           2019-11-02 12:48:07.000 2019-11-02 12:48:07.000 0
26      5        13039471    13039471   1           2019-11-10 15:05:07.000 2019-11-10 15:05:07.000 0

Expected Result :

NetworkNode | Count of Happening | Sum of Duration for all Happenings (Min or Sec)
24          | 10                 | 50
25          | 14                 | 46
26          | 29                 | 128
27          | 3                  | 7
28          | 21                 | 39
29          | 75                 | 481

***** Meaning of Happening** : Duration between EventType 1 to EventType 5 for each NetworkNode.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM