Короче говоря, я хочу создать запрос, который поможет мне найти наилучшие доступные места для концертного типа, очень похожего на «Найти лучшие доступные места» на Ticketmaster.com, где необходимо найти запрошенное количество мест, ближайших на сцену и места должны быть в последовательном порядке.
Учитывая этот пример таблицы:
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
)
И учитывая этот скрипт для заполнения таблицы:
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
Каков наилучший запрос для поиска x числа последовательных / смежных мест?
Ниже приведено мое текущее решение, которое требует как минимум 3 запроса от моего приложения.
Например, если клиент запросил 8 из следующих лучших доступных мест, я бы запустил этот запрос:
/* 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
Что даст такой набор результатов, как этот:
| SectionId | Priority | SeatCount |
|-----------|----------|-----------|
| 1 | 1 | 544 |
| 2 | 2 | 554 |
| 3 | 3 | 552 |
В приложении будет указано: «Есть ли 8 мест с приоритетом 1?» и с указанным выше набором результатов ответ будет положительным, так что давайте посчитаем количество доступных строк для соответствующего раздела, который является Разделом 1. Вот запрос для этого:
SELECT RowId,
COUNT(SeatId) AS 'Seat Count'
FROM @Seats
WHERE SectionId = 1
AND StatusCd = 'A'
GROUP BY RowId
Что даст такой набор результатов, как этот:
| RowId | SeatCount |
|-------|-----------|
| A | 21 |
| B | 18 |
| C | 22 |
Приложение будет смотреть на эти результаты и задавать тот же вопрос, начиная с первого ряда: «Есть ли 8 мест в строке A?» При указанных выше результатах ответ будет положительным, поэтому в это время приложение будет запрашивать все места в строке A с помощью этого запроса:
SELECT *
FROM @Seats
WHERE SectionId = 1
AND RowId = 'A'
Что даст такой набор результатов, как этот:
| 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 |
В это время приложение будет перебирать результаты, пытаясь найти 8 мест подряд с StatusCd 'A' для доступных.
Я уверен, что существует гораздо более эффективный метод запроса последовательных записей в базе данных без необходимости загружать целые строки и делать это в коде.
Моим лучшим предположением для оптимального решения было бы сделать самостоятельное соединение на столе и выполнить какое-то приращение SeatId или что-то в этом роде.
Любая помощь или предложения приветствуются.