Question

In a nutshell, I wish to create a query that will help me find the best available seats for a concert type venue much like Ticketmaster.com's "Find Best Available Seats" where the requirements are to find the requested number of seats closest to the stage and the seats must be in sequential order.

Given this example table:

DECLARE @Seats TABLE
(
    SectionId   INT         NOT NULL,
    RowId       VARCHAR(2)  NOT NULL,
    SeatId      INT         NOT NULL,
    Priority    INT         NOT NULL, /* Used to determine closeness to the stage and/or order to search in */
    StatusCd    CHAR(1)     NOT NULL, /* A for Available, H for Held, P for Purchased, etc. */
    Cost        MONEY       NOT NULL
)

And given this script to populate the table:

DECLARE @SectionCounter INT
DECLARE @RowCounter INT
DECLARE @SeatCounter INT

SET     @SectionCounter = 1
SET     @RowCounter = 1

WHILE   @SectionCounter <= 10
BEGIN

    WHILE   @RowCounter <= 26
    BEGIN

        SET @SeatCounter = 1

        WHILE @SeatCounter <= 26
        BEGIN       

            INSERT INTO @Seats
            ( SectionId ,
              RowId ,
              SeatId ,
              Priority ,
              StatusCd ,
              Cost
            )
            VALUES 
            ( @SectionCounter ,
              CHAR(64 + @RowCounter) ,
              @SeatCounter ,
              1 ,
              (
                /* Randomly setting certain seats as purchased */
                SELECT  CASE
                        WHEN @SeatCounter IN 
                        (
                            1,2,9,10,
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0)),
                            (ROUND(((26 - 1 -1) * RAND() + 1), 0))
                        )
                        THEN 'P' ELSE 'A' END) ,
              (
                SELECT  CASE
                        WHEN @SectionCounter IN (1,2)
                        THEN 75.00 ELSE 25.00 END
              )
            )

            SET @SeatCounter = @SeatCounter + 1

        END

        SET @RowCounter = @RowCounter + 1

    END

    SET     @RowCounter = 1
    SET @SectionCounter = @SectionCounter + 1

END

What is the best query to find an x number of sequential / contiguous seats?

Below is my current solution, which requires at minimum 3 queries by my application.

For example, if a customer requested 8 of the next best available seats, I would run this query:

/* Get each sections available seat count */
SELECT  SectionId,
        Priority,
        COUNT(SeatId) AS 'Seat Count'
FROM    @Seats
WHERE   StatusCd = 'A' /* A = Available. */
GROUP BY SectionId, Priority
ORDER BY Priority

Which would produce a result set such as this:

| SectionId | Priority | SeatCount |
|-----------|----------|-----------|
| 1         | 1        | 544       |
| 2         | 2        | 554       |
| 3         | 3        | 552       |

The application would say "Are there 8 seats available with a Priority of 1?" and with the above result set, the answer would be yes, so let's get the available row counts for the corresponding section, which is Section 1. Here's the query for that:

SELECT  RowId,
        COUNT(SeatId) AS 'Seat Count'
FROM    @Seats
WHERE   SectionId = 1
        AND StatusCd = 'A'
GROUP BY RowId

Which would produce a result set such as this:

| RowId | SeatCount |
|-------|-----------|
| A     | 21        |
| B     | 18        |
| C     | 22        |

The application would look at these results and ask the same question starting with the first row, "Are there 8 seats available in Row A?" With the above results, the answer would be yes, so at that time the application would query for all seats in Row A with this query:

SELECT  *
FROM    @Seats
WHERE   SectionId = 1
AND     RowId = 'A'

Which would produce a result set such as this:

| SectionId | RowId | SeatId | Priority | StatusCd | Cost  |
|-----------|-------|--------|----------|----------|-------|
| 1         | A     | 1      | 1        | P        | 75.00 |
| 1         | A     | 2      | 1        | P        | 75.00 |
| 1         | A     | 3      | 1        | A        | 75.00 |
| 1         | A     | 4      | 1        | A        | 75.00 |
| 1         | A     | 5      | 1        | A        | 75.00 |

At that time, the application would iterate through the results attempting to find 8 seats in a row with a StatusCd of 'A' for available.

I'm sure there is a much more efficient method of querying for sequential records in the database without having to load entire rows and doing it in code.

My best guess for an optimal solution would be to do a self join on the table and doing some kind of incrementing of the SeatId or something along those lines.

Any help or suggestions is greatly appreciated.

No correct solution

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top