A T-SQL simple puzzle on ASP.NET forum.

http://forums.asp.net/p/1299660/2535207.aspx#2535207

Lets say that I've got two tables:

ROOM:
ID_ROOM : int
Name: Nvarchar(50)

RESERVATION
ID_RESERVATION : int // unique ID of reservation
ID_ROOM : int // which room is reserved
DATE: SmallDateTime // date of reservation
HOUR_BEGINNING : int // hour in which reservation begin
HOUR_END : int // hour in which reservation end

And now I want to find ALL rooms which can be reserved for at least DURATION(int) hours between HOUR_SEEK_START(int) and HOUR_SEEK_END(int) in day DAY(SmallDateTime). For example: I want to find all rooms which can be reserved for at least 2 hours between 10 and 16 on 16.05.2008. I hope I set the record straight.

 My reply was:

---

First, let's cast the phrase "for at least DURATION(int) hours between HOUR_SEEK_START(int) and HOUR_SEEK_END(int)" into something set oriented. Why not create a temp table to keep potentially good time intervals, those of DURATION(int) length that could fit between HOUR_SEEK_START(int) and HOUR_SEEK_END(int). Later for each room we'll just check out if among these intervals there will be one not spoiled by related reservation records.

  

  CREATE TABLE #Hours(
    IndexId int IDENTITY (0, 1) NOT NULL, 
    hr nchar(8))
    
  INSERT INTO #Hours(hr) VALUES ('0');  INSERT INTO #Hours(hr) VALUES ('1');
  INSERT INTO #Hours(hr) VALUES ('2');  INSERT INTO #Hours(hr) VALUES ('3');
  INSERT INTO #Hours(hr) VALUES ('4');  INSERT INTO #Hours(hr) VALUES ('5');
  INSERT INTO #Hours(hr) VALUES ('6');  INSERT INTO #Hours(hr) VALUES ('7');
  INSERT INTO #Hours(hr) VALUES ('8');  INSERT INTO #Hours(hr) VALUES ('9');
  INSERT INTO #Hours(hr) VALUES ('10');  INSERT INTO #Hours(hr) VALUES ('11');
  INSERT INTO #Hours(hr) VALUES ('12');  INSERT INTO #Hours(hr) VALUES ('13');
  INSERT INTO #Hours(hr) VALUES ('14');  INSERT INTO #Hours(hr) VALUES ('15');
  INSERT INTO #Hours(hr) VALUES ('16');  INSERT INTO #Hours(hr) VALUES ('17');
  INSERT INTO #Hours(hr) VALUES ('18');  INSERT INTO #Hours(hr) VALUES ('19');
  INSERT INTO #Hours(hr) VALUES ('20');  INSERT INTO #Hours(hr) VALUES ('21');
  INSERT INTO #Hours(hr) VALUES ('22');  INSERT INTO #Hours(hr) VALUES ('23');
  
  CREATE TABLE #TimeSpansRequested(hr1 int, hr2 int)
  
  INSERT INTO #TimeSpansRequested(hr1, hr2) 
  SELECT h1.IndexId, h2.IndexId  
  FROM #Hours h1, #Hours h2
  WHERE (h2.IndexId - h1.IndexId = @DURATION) 
        AND (h1.IndexId BETWEEN @HOUR_SEEK_START AND (@HOUR_SEEK_END - @DURATION))

The above T-SQL code is self explaining. We self joined #Hours temp table to get a set of time intervals, and then restricted the intervals to those of @DURATION length that are between @HOUR_SEEK_START and @HOUR_SEEK_END hours. The result is getting into #TimeSpansRequested temp table. Its records are just pairs of (hr1, hr2) hours - borders of pottentially good intervals. And finally:

  

 SELECT * 
 FROM ROOM           
 WHERE EXISTS(SELECT hr1
              FROM #TimeSpansRequested
              WHERE NOT EXISTS(SELECT ID_TIMESPAN 
                               FROM RESERVATION  
                               WHERE (RESERVATION.ID_OBJ = ROOM.ID_OBJ)
                                      AND ([DATE] = @DAY)
                                      AND ((hr1 BETWEEN HOUR_BEGINNING AND HOUR_END)
                                      OR (hr2 BETWEEN HOUR_BEGINNING AND HOUR_END))
                                     )
              )

 In the code above we are checking out for each door if exists some potentially good interval that is not spoiled by any of reservation timespan. 

No Comments