使用SQL查询选择连续的数字

时间:2010-02-25 14:16:00

标签: php mysql

这是剧院座位预订计划。

Seat No Status
1 Booked
2 Available
3 Available
4 Available
5 Available
6 Available
7 Booked
8 Available
9 Available
10 Available

如果有人想预订6张门票,他将获得2号至6号座位和8号座位 如果有人只想预订5张门票,他将获得2号到6号座位

如果可用的相邻席位超过所要求的席位,我如何知道使用SQL查询(或PHP代码)?

顺序座位选择是我需要实现的主要目标。

7 个答案:

答案 0 :(得分:5)

试试这个:

select seat, status
from seats
where seat >= (
   select a.seat
   from seats a
      left join seats b on 
         a.seat < b.seat and
         b.seat < a.seat + 4 and
         b.status = 'Available'
   where a.status = 'Available'
   group by a.seat
   having count(b.seat)+1 = 4
   )
limit 4

设置选择四个连续席位。将所有“4”实例调整到所需的座位数,以获得您想要的内容。

答案 1 :(得分:0)

一通。把你的号码代替?。在满足您的要求时,为您提供第一个序列中的席位编号,如果未找到序列,则为NULL

SET @FOUND = 0;
SET @SEAT_MATCHED = NULL;

SELECT
    IF(@FOUND < ?,
        @FOUND := IF(status == 'Booked', 0, @FROM + 1),
        @SEAT_MATCHED := IFNULL(@SEAT_MATCHED, seat_no)
    )
FROM seats
ORDER BY seat_no

SELECT @SEAT_MATCHED;

更多阅读:Control Flow FunctionsUser Variables

NB!此方法仅适用于分析间隔内记录很少的情况!

更新。也许您可以将行中已预订座位的位掩码存储为整数。例如,对于16个席位的行,36884(二进制为1001000000010100)表示第3,第5,第13和第16个席位已预订。它会减少MySQL负载。然后你可以这样做代码:

<?php

header('Content-Type: text/plain');

// data you get from DB
$seats = bindec('1001000000010100');
$num_seats = 16;

// calculate consecutive free seats
$seats_info = array();
for ($i = 0; $i < $num_seats; $i++, $seats >>= 1) {
    if ($seats & 1) {
        if (isset($first)) {
            $seats_info[$first] = $i - $first;
            unset($first);
        }
    }
    else {
        if (!isset($first)) {
            $first = $i;
        }
    }
}

// output sequences
var_export($seats_info);

?>

输出:

array (
  0 => 2,
  3 => 1,
  5 => 7,
  13 => 2,
)

0 1st 席位。

答案 2 :(得分:0)

最好将预订/可用表示为二进制数字(例如,1个免费,0个预订)。如果这样做,您可以优雅地使用聚合函数:

  select seat as n from seats where
      $num_seats = (select sum(status) from seats
         where seat between n and n + $num_seats - 1)

答案 3 :(得分:0)

SELECT a.seat_no     SEAT1,
       a.seat_no + 1 SEAT2,
       a.seat_no + 2 SEAT3  
  FROM theater a
 WHERE a.availability = 'Y'
   AND seat_no + 1 = (SELECT b.seat_no 
                        FROM theater b 
                       WHERE b.seat_no = a.seat_no + 1 
                         and b.availability = 'Y')
   AND seat_no + 2 = (SELECT b.seat_no 
                        FROM theater b 
                       WHERE b.seat_no = a.seat_no + 2 
                         and b.availability = 'Y');

答案 4 :(得分:0)

select distinct S2.seat
from (
   select a.seat
   from seats a
      left join seats b on 
         a.seat <= b.seat and
         a.seat + 3 >= b.seat and
         a.availability = 1 and b.availability = 1
   group by a.seat
   having count(b.seat) = 4
   ) as S1
   join 
   seats as S2
   on 
   S1.seat <= S2.seat and S1.seat+3 >= S2.seat
order by S2.seat_no
limit 4;

答案 5 :(得分:-1)

我建议使用SQL和PHP的一种递归算法。你需要X座位。

  1. 使用SQL查询选择所有可用席位,您将获得N个可用席位(如果N

  2. 在php中分析结果并使用相邻席位组大小作为关键字存储它们(可能有多个具有相同大小的组)

      

    '5'=&gt; (2,3,4,5,6)

         

    '2'=&gt; (8,9)

  3. 尝试找到具有X席位的群组

  4. 如果找不到,请选择尺寸为&gt;的最近的组。 X(对于X = 4,它的组'5')

  5. 如果找不到更大的组,请取出最大的组(大小为Y的组),然后重复步骤3 - 5,其中X = X - Y

答案 6 :(得分:-3)

编辑:由于我在这里误解了一个SQL语句,它将返回第一个免费的所有第一个免费席位和相邻席位的数量。更多的免费座位是第一位的。

SELECT count(1) free,(
 CASE status
  WHEN "Booked" THEN
   @prev:=NULL
  ELSE
   @prev:=COALESCE(cast(@prev as unsigned), seat_no)
  END) first
FROM 
 (SELECT @prev:=null) f,
 (SELECT seat_no, status FROM seats ORDER BY seat_no) seats
GROUP BY first
HAVING first>=0
ORDER BY 1 DESC, 2

因此,对于您的示例,它将返回:

free | first
-----------
   5    2
   3    8

如果您只对第一个可以满足您要求的顺序座位感兴趣而且不再仅仅为免费座位数添加条件,那么如果您想要增加free>=3的3个座位,则可以执行此操作:

SELECT count(1) free,(
 CASE status
  WHEN "Booked" THEN
   @prev:=NULL
  ELSE
   @prev:=COALESCE(cast(@prev as unsigned), seat_no)
  END) first
FROM 
 (SELECT @prev:=null) f,
 (SELECT seat_no, status FROM seats ORDER BY seat_no) seats
GROUP BY first
HAVING first>0 AND free>=3
LIMIT 1

这将输出:

free | first
------------
   5    2