2010-02-25 30 views
4

這是一個影院座位預訂計劃。使用SQL查詢選擇連續號碼

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代碼)?

連續座位選擇是我需要實現的主要目標。

+0

可以在那裏有多少個座位? – codeholic 2010-02-25 14:25:13

+0

一次最多可容納80個座位 – shantanuo 2010-02-25 14:52:03

+0

如果有人要求3個座位,您是否希望爲他們提供8-10個座位(對於想要更大規模的人來說,保留2-6個座位),還是給他們連續三個座位? – outis 2010-02-25 15:13:41

回答

4

嘗試這種情況:

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」的所有實例到所需數量的座位,以獲得您想要的。

+0

錯誤1242(21000):子查詢返回多於1行但子查詢運行良好,這正是我所需要的。謝謝。 – shantanuo 2010-02-26 09:11:01

-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 

如果你只在第一序貫座椅可滿足您的要求,並沒有更多的只是添加的免費座位數的情況感興趣,所以如果你想3個席位將free>=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 
+0

好吧,這將提供第一個可用的座位,而不僅僅是相鄰的座位。例如0101010111,我要求3個席位,你的選擇會給我那些分開的,我實際上想要最後3個彼此相鄰 – rytis 2010-02-25 14:29:31

+0

是的,我知道,在他的例子中,如果它請求6個席位,它也選擇自從第七位被排除後,第八位被排除了,所以這回答了他不想要的內容? – Patrick 2010-02-25 14:34:48

+0

你的結果與他的要求相符,只是因爲他的例子是以這種方式設置的。如果他有以下佈局作爲他的例子:0101010111111110你的選擇不符合他想要的,這將是最後8個席位 – rytis 2010-02-25 14:41:10

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個座位的行,編號爲368841001000000010100的二進制)意味着預定了第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是座位。

+0

換句話說,如果座位不緊挨着,它不會給你任何東西嗎?就像要求6個席位一樣,bt只有5個在組中,而最後一個可能來自下一個組,你仍然會得到NULL? – rytis 2010-02-25 14:47:26

+0

是的。但它比山坦諾問得更多。如果你喜歡,這個查詢可以稍微修改以滿足你的要求。 – codeholic 2010-02-25 14:50:30

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

我會建議一個使用SQL和PHP的遞歸算法。你需要X個座位。

  1. 使用SQL查詢選擇所有可用座位,您會收到N個可用座位(如果N < X,錯誤)

  2. 在PHP的分析結果,並使用相鄰座位組存儲它們大小的一個關鍵(有可能是多個組具有相同的大小)

    '5'=>(2,3,4,5,6)

    '2'=>(8,9)

  3. 試圖找到與X席位組

  4. 如果沒有找到,挑最接近組大小> X(對於X = 4這是一羣 '5')

  5. 如果沒有更大組發現,取出最大可用的(組與尺寸Y),然後重複步驟3 - 5其中X =說明X - Y

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');