TSQL Challenges

TSQL Challenges intend to help you to test and enhance SET based querying skills using TSQL.





TSQL Challenge 23 - Calculate the uptime and downtime of a system by reading the data from an audit log

It is again time to play with some date/time values. This challenge involves reading the audit log entries generated by a monitoring application and create a report that shows the up-time and down-time of a system that the application is monitoring.

Red Gate SQL Backup Pro is sponsoring TSQL Challenge 23. The top winner of TSQL Challenge 23 will win a license of SQL Backup Pro worth $795, and a Red Gate goodie bag including a T-shirt, frisbee and more.

The Context

NP Corporation is using a Legacy Application that their employees use to perform some of the day-to-day operations. The system is quite old, the people that built the system is not around any more. Due to some unknown reasons the system hangs frequently and the only way to bring it up is to reboot the server. Though it is not an acceptable behavior, there is no alternative and the management of NP corporation has decided to migrate to a new system soon. The management wants to keep track of the uptime and downtime of the system and created a monitoring application that populate an audit table as given below.

AuditTime               IsOnline
----------------------- --------
2010-01-01 10:11:23.000 1
2010-01-01 10:14:03.000 1
2010-01-01 10:19:36.000 1
2010-01-01 10:23:59.000 0
2010-01-01 10:27:14.000 0
2010-01-01 10:31:24.000 1
2010-01-01 10:34:15.000 1
2010-01-01 10:36:11.000 0
2010-01-01 10:39:40.000 1
2010-01-01 10:42:23.000 1

The monitoring application checks the status of the application preriodically and logs the status to the audit table. If the server is online, it writes "1" and "0" if the system is not online. "AuditTime" column stores the time at which the monitoring application checked the status of the server. The monitoring application has a custom logic that decides the interval at which the audit takes place.

I know, none of you are happy with the way the system works and the monitoring application behaves. Some of you might even refuse to work in such an environment arguing the whole setup does not make sense. However, for the purpose of this challenge, assume that you have no choice than to live with it!

The Challenge

Your job is to write a query that produces a report showing the uptime and downtime of the system. Here is the output that you need to produce, based on the given input data.

TimeFrom            TimeTo              IsOnline
------------------- ------------------- --------
2010-01-01 10:00:00 2010-01-01 10:21:47 Yes
2010-01-01 10:21:47 2010-01-01 10:29:19 No
2010-01-01 10:29:19 2010-01-01 10:35:13 Yes
2010-01-01 10:35:13 2010-01-01 10:37:55 No
2010-01-01 10:37:55 2010-01-01 11:00:00 Yes
Rules

There are a few points to keep in mind when generating the output data.

  • The solution should be a single query that starts with a "SELECT", ";WITH" or "WITH"
  • The first and last periods start and end on the hour preceding and following. (Note that the "TimeFrom" on the first row is 10 AM and "TimeTo" in the last row is 11 AM. For example, if the first reading is at 08:23:45, the first period in the resultset should start at 8:00:00. If the last reading is at 21:23:45, the last period in the result should end at 22:00:00.
  • All rows except for the first and last should finish at the midpoint between the readings. For example the reading at 10:19 found the system to be online and the reading at 10:23 found it to be offline. Since the server went offline some time between the two readings, you should take the midpoint between the readings: 10:21
  • The first and last periods should be whatever status the first and last readings indicate (rather than assuming that the period starts up or down).
  • The result should use the datetime type, rounded down to the nearest second. Each reading is taken at an exact second - there is no millisecond component.

Sample Data

Here is the script to genreate the source tables and populate the sample data

IF OBJECT_ID('TC23','U') IS NOT NULL BEGIN
	DROP TABLE TC23
END
GO

CREATE TABLE TC23(
	AuditTime DATETIME,
	IsOnline BIT -- 0:Down, 1:Up
)
GO

INSERT INTO TC23(AuditTime, IsOnline)
SELECT '2010-01-01T10:11:23', 1 UNION ALL
SELECT '2010-01-01T10:14:03', 1 UNION ALL
SELECT '2010-01-01T10:19:36', 1 UNION ALL
SELECT '2010-01-01T10:23:59', 0 UNION ALL
SELECT '2010-01-01T10:27:14', 0 UNION ALL
SELECT '2010-01-01T10:31:24', 1 UNION ALL
SELECT '2010-01-01T10:34:15', 1 UNION ALL
SELECT '2010-01-01T10:36:11', 0 UNION ALL
SELECT '2010-01-01T10:39:40', 1 UNION ALL
SELECT '2010-01-01T10:42:23', 1 

SELECT * FROM TC23
/*
AuditTime               IsOnline
----------------------- --------
2010-01-01 10:11:23.000 1
2010-01-01 10:14:03.000 1
2010-01-01 10:19:36.000 1
2010-01-01 10:23:59.000 0
2010-01-01 10:27:14.000 0
2010-01-01 10:31:24.000 1
2010-01-01 10:34:15.000 1
2010-01-01 10:36:11.000 0
2010-01-01 10:39:40.000 1
2010-01-01 10:42:23.000 1
*/

Notes

  1. Read the Submission Guidelines and make sure that your solution follows them.
  2. The solution should work on SQL Server 2005, 2008 or later versions
  3. Use this forum for any questions related to TSQL Challenge #23
  4. Last Date to submit your entries: 22 February 2010 Midnight GMT.
And the Winner Gets...

Red Gate SQL Backup Pro is sponsoring TSQL Challenge 23. The top winner of TSQL Challenge 23 will win a license of SQL Backup Pro worth $795, and a Red Gate goodie bag including a T-shirt, frisbee and more.

Note: In case more than one user comes in the first place, we will select the winner through a lucky draw

Special thanks to the Early Review Team, especially Sergejack and dave ballantyne who reviewed the challenge and provided valuable inputs to make the challenge description and rules more comprehensible. Rui, Peter and Rob from the TSQL Challenge Team worked really hard on this challenge to get it to the way you see it now.


Comments

Ramireddy said:

Nice challenge... reminds famous problem.... eager to post an quick solution... but no time... need to wait until office is over.....

# February 8, 2010 3:36 AM

reganwick said:

I have a recommendation that new challenges be posted only after a challenge eval is complete.

For example, once challenge 16 results are complete, then post challenge 23

# February 8, 2010 1:25 PM

Jacob Sebastian said:

@reganwick,

your recommendation is valid and we understand it is a bit frustrating to bear the delay in seeing the results.

As I have mentioned a few times in the recent posts, we are speeding up the evaluation process to catch up. You will see the improvement very shortly (in 2-3 weeks) and we will be able to reduce the delay between the closure of a challenge and the results to 7 to 14 days.

It is just a matter of another few weeks and we will catch up with all the previous challenges and you will see the results. So please bear with us.

# February 8, 2010 8:52 PM

reganwick said:

Yes. I have read those posts from you. My recommendation was within that context. I just thought it would make more sense for the project not to backlog too much.

# February 8, 2010 11:22 PM

Michael Lewis said:

I have noticed in the examples given that you are rounding down to the nearest second, when SQL Server naturally rounds up.  Does it matter either way, or do we need to always round down?

Incidentally, I would post this in the forum but I don't seem to have permission to do so.

Thanks

# February 9, 2010 3:56 AM

Jacob Sebastian said:

@Michael, You should round down to the nearest second.

You need to be a member of the group beyondrelational.com/.../default.aspx to be able to post in the forums.

# February 9, 2010 7:38 AM

karinloos said:

Can we assume that the audit table is already in the correct sort order (ie date asc )

# February 9, 2010 7:48 AM

Jacob Sebastian said:

@karinloos,

I would suggest such an assumption may be incorrect, because a SQL Server table does not guarantee the order of the rows it returns, unless you specify a sort order. So let us not assume any physical order of rows.

# February 9, 2010 8:05 AM

Eric said:

I like this challenge.  It's a good one.

# February 9, 2010 11:02 AM

dishdy said:

The rules say that "the first and last periods start and end on the hour preceding and following." If the first period in the data is exactly, say, 17:00:00 then the rule implies that this should be shown as 16:00:00 - even though someone might claim this is unreasonable. Same for the last period.

Can you please clear this up.

Thnks.

# February 11, 2010 5:38 AM

karinloos said:

I interpret it differently again, I thought that the object was to round down to the nearest hour on the first period and round up to the last one

# February 11, 2010 5:54 AM

dishdy said:

The rules do NOT use the terminology 'rounding down' or 'rounding up'. That's why I'm asking that this be make clear.

# February 11, 2010 6:18 AM

Jacob Sebastian said:

@Dishdy,

you are right. if the first reading is done at 17:00, your code should assume the period of the first reading as 16:00 to 17:00 (which implies that the previous reading was done at 16:00).

# February 11, 2010 7:39 AM

jmc_bkk said:

Jacob your last post isn't clear. The way I read the instructions was that the first periods start time should be "rounded" down to that time's whole hour (e.g., AuditTime = 10:11:23 becomes 10:00:00 in the final output). For the last AuditTime in the set, we round "up" to the next hour (e.g., 10:42:23 becomes 11:00:00). Now what if the data (the first and last records) starts or ends on a whole hour? My assumption is no rounding "up" or "down" is needed, the first/last time period starts/ends on a whole hour already so leave as is (and your code should plan for this). Please verify (or correct).

# February 11, 2010 12:09 PM

dishdy said:

As I said earlier, the term "rounded" was never used (except when calculating the midpoint between two time stamps). Instead the term "preceding" was used for the first time stamp and "following" for the last time stamp. The hour "preceeding" 17:00:00, as far as I understand this term, is 16:00:00.

In my opinion, we shouldn't let this technicality distract us. Maybe the simplest way around this issue is to simply state that the first and last time stamp will never be an exact hour. In that case, both terms will produce the same result.

# February 11, 2010 3:15 PM

Mark said:

Can we assume that the audit times are unique and non NULL?

# February 12, 2010 2:14 AM

Rui Carvalho said:

@dishdy,

As Jacob said, you are right in your reading. This is just to have a starting and ending point and to have a common logic even if the first ping falls exactly on an hour. But as you said, don't be distracted with that ;-)

@Mark,

I can't said exactly now if we'll test that point but in all the cases it doesn't fit any logic.

In all the cases, your need to write your query to work with the provided sample data, after that it's up to you to take in consideration the facts you judge important

# February 12, 2010 4:15 AM

Niladri Biswas said:

Could any one please confirm whether

2010-01-01 10:37:55 is correct?

I guess it will be  2010-01-01 10:37:25

i.e. the second's field will be 25 instead of 55.

Please confirm.

# February 15, 2010 9:56 PM

rob_farley said:

Niladri,

10:36:11 to 10:37:25 is 1m 14s.  

10:37:25 to 10:39:40 is 2m 15s.    

10:36:11 to 10:37:55 is 1m 44s.  

10:37:55 to 10:39:40 is 1m 45s.

Therefore, the correct time is 10:37:55

Rob    

# February 16, 2010 5:32 AM