SQL - 查找给定大小的连续条目

时间:2010-04-03 04:07:16

标签: sql mysql

我正在研究一个预留座位的系统。用户输入他们希望保留的座位数,数据库将返回一组建议的座位,这些座位之前未预留,与预订的座位数相匹配。

例如,如果我有桌子:

SeatID | Reserved
-----------------
1      | false
2      | true
3      | false
4      | false
5      | false
6      | true
7      | true
8      | false
9      | false
10     | true

并且用户输入他们希望保留2个席位,我希望查询返回座位(3,4),(4,5)和(8,9)不保留并匹配给定的号码输入席位。座位分为部分和行。连续座位必须在同一行。

我如何构建此查询以使其找到与给定输入匹配的所有可用连续席位?

3 个答案:

答案 0 :(得分:2)

使用SQL Server 2005/2008:

WITH FreeSeatGroups AS
(
    SELECT S1.SeatID AS StartID,
           (SELECT MIN(S2.SeatID)
            FROM Seats S2 
            WHERE S2.SeatID > S1.SeatID
            AND S2.Reserved = 1) - S1.SeatID AS FreeSeatCount
    FROM Seats AS S1
    WHERE S1.Reserved = 0
)
SELECT StartID, FreeSeatCount
FROM FreeSeatGroups
WHERE FreeSeatCount >= 2

请注意,这会返回ID 3,4和8,因为每个位置都有两个免费席位。

这也假设座位ID始终是连续的。如果没有,您可以进入ROW_NUMBER()

答案 1 :(得分:1)

此解决方案仅适用于SQL Server 2005+或其他支持CTE的产品。另外,我假设“保留”输入的存储方式与示例中的字符串相反,而不是位。最后,我认为SeatId是完全顺序的:

   With
    StartSeats As
    (
    Select SeatId + 1 As SeatId
    From Seats As S
    Where Reserved = 'true'
        And Not Exists(
                        Select 1
                        From Seats As S2
                        Where S2.SeatId = S.SeatId + 1
                            And S2.Reserved = 'true'
                        )
        And SeatId < ( Select Max(S1.SeatId) From Seats As S1 ) 
    Union All
    Select SeatId
    From Seats
    Where SeatId = 1 
        And Reserved = 'false'
    Union All
    Select SeatId
    From Seats
    Where SeatId = ( Select Max(S1.SeatId) From Seats As S1 )   
        And Reserved = 'false'
    )
    , SeatRanges As
    (
    Select S1.SeatId As FirstOpenSeat, Min(S2.SeatId) As LastReservedSeat
    From StartSeats As S1
        Left Join Seats As S2
            On S2.SeatId > S1.SeatId
                And S2.Reserved = 'true'
    Group By S1.SeatId          
    )
Select *
From SeatRanges
Where LastReservedSeat - FirstOpenSeat = 2

答案 2 :(得分:0)

WITH FreeSeatGroups AS
(
   select s1.ss StartID,(select  min (s2.ss) 
   from test123 s2
   WHERE S2.ss >= S1.ss
   and S2.rr = 1) -s1.ss FreeSeatCount  from test123 s1
)
SELECT StartID, FreeSeatCount
FROM FreeSeatGroups
WHERE FreeSeatCount >= 1