2010-04-03 50 views
4

我正在致力于预留座位的系统。用户输入他们希望保留的座位数量,并且数据库将返回一组先前未保留的与所保留的座位数相匹配的建议座位。SQL - 查找给定大小的连续条目

举例来说,如果我有表:

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)不保留并且与给定数量的输入座位相匹配。席位被组织成部分和行。连续席位必须位于同一行。

我该如何解决这个查询的结构问题,以便找到与给定输入匹配的所有可用连续席位?

+1

SQL什么味道? MySQL的? SQL Server 2000? 2005年? 2008年? – Thomas 2010-04-03 04:11:16

+0

对不起,是MySQL的。 – 2010-04-03 05:01:24

回答

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()

+0

感谢您的帮助。不得不为MySQL修改它,但除此之外,它完美地工作。 – 2010-04-03 05:00:55

+0

很酷。乐于帮助! – 2010-04-03 05:03:53

1

此解决方案仅适用于SQL Server 2005+或某些其他支持CTE的产品。另外,我假定“Reserved”中的内容与您的示例中的字符串相同,而不是一点。最后,我认为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 
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