[英]How would you get the Largest / MAX COUNT of Sequential / Contiguous records meeting a Criteria using T-SQL
簡而言之,我希望創建一個查詢,以幫助我找到音樂會類型場地的最佳可用座位,就像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 |
應用程序將查看這些結果,並從第一行開始詢問相同的問題:“ A行中有8個席位嗎?” 根據以上結果,答案是肯定的,因此當時應用程序將使用此查詢來查詢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進行某種形式的增量或沿這些直線進行某種方式。
任何幫助或建議,我們將不勝感激。
這應該使您入門。 就自我加入而言,您處在正確的軌道上,這是另一種方式。
這將為您提供具有相同優先級,部分,行的前8個座位,狀態按優先級,部分,行的先后順序顯示為“ A”。 如果我誤會了什么,請糾正我。
DECLARE @number_seats AS INTEGER = 8;
WITH T1 AS (
SELECT S.*,
SeatId - ROW_NUMBER() OVER(PARTITION BY Priority, SectionId, RowId, StatusCd ORDER BY SeatId) AS grp
FROM #seats AS S
),
T2 AS (
SELECT Priority AS Priority,
SectionId AS Section,
RowId AS RowId,
StatusCd AS StatusCd,
MIN(SeatId) AS StartingSeat,
MAX(SeatId) AS EndingSeat,
COUNT(*) AS Seats
FROM T1
GROUP BY Priority, SectionId, RowId, StatusCd, grp
),
T3 AS (
SELECT TOP 1 *
FROM T2
WHERE T2.Seats >= @number_seats and StatusCd = 'A'
ORDER BY Priority, Section, RowId, StartingSeat
)
SELECT S.*
FROM T3 JOIN #seats AS S ON
(
T3.Priority = S.Priority AND
T3.Section = S.SectionId AND
T3.RowId = S.RowId AND
S.SeatId BETWEEN T3.StartingSeat AND T3.StartingSeat + @number_seats - 1
)
ORDER BY Priority, Section, RowId, StartingSeat
結果:
SectionId RowId SeatId Priority StatusCd Cost
----------- ----- ----------- ----------- -------- ---------------------
1 A 11 1 A 75.00
1 A 12 1 A 75.00
1 A 13 1 A 75.00
1 A 14 1 A 75.00
1 A 15 1 A 75.00
1 A 16 1 A 75.00
1 A 17 1 A 75.00
1 A 18 1 A 75.00
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.