SQL sorgusu kullanarak ardışık sayılar seçerek

5 Cevap php

Burada bir tiyatro koltuk rezervasyon planıdır.

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

If someone wants to book 6 tickets, he will get Seat No. 2 to 6 and seat No. 8 And if someone wants to book only 5 tickets, he will get Seat No. 2 to 6

Mevcut bitişik koltuk talep koltuk daha fazla olup olmadığını nasıl SQL sorgusu (veya PHP kodu) kullanılarak biliyor musunuz?

Sıralı koltuk seçimi ben ulaşmak için gereken birincil hedefidir.

5 Cevap

Bu deneyin:

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

Bu arka arkaya dört koltuk seçmek için ayarlanır. İstediğini elde etmek koltuk istenilen sayıda "4" tüm örneklerini ayarlayın.

binary sayılar (örneğin 1-ücretsiz, 0-kart) olarak Rezervasyon / Mevcut temsil etmek daha iyidir. Bunu yaparsanız, size zarif toplama işlevleri yararlanabilirler:

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

Bir pas. Yerine sana numarasını koymak ?. Hiçbir dizisi bulursa ilk şartı bir araya geldi dizisi, ya da NULL size koltuk sayısını verir.

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;

Daha fazla okuma: Control Flow Functions, User Variables

Birkaç kayıtları incelendiğinde aralıkta varsa NB! Bu yaklaşım geçerlidir!

Update. Belki bir tamsayı olarak satırdaki rezerve koltuk bit maskesi saklayabilirsiniz. Örneğin, 16-koltukları için numarasını 36884 (1001000000010100 ikili olarak) anlamına gelir satır 3rd, 5th, 13th and 16th seats are booked. Bu MySQL yükü azaltacak. Ve sonra bu gibi kod yapabilirdi:

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

?>

Bu çıkışlar:

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

0 1st koltuğu.

Ben SQL ve PHP kullanarak bir özyinelemeli algoritma öneririm. Sen X koltuk gerekir.

  1. SQL sorgusunu kullanarak tüm Mevcut koltuk seçin, siz N mevcut koltuk almak (Eğer N

  2. Php sonuçları analiz ve (aynı boyutta birden fazla grup var olabilir), bir anahtar olarak bitişik koltuk grupları boyutlarını kullanarak saklayabilirsiniz

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

    '2 '=> (8, 9)

  3. X sandalyeyle grubunu bulmak için çalışın

  4. Bulunmazsa eğer, (X = 4 için 'grup '5 bulunuyor) boyutu> X ile yakın grubu seçmek

  5. Hiçbir büyük gruplar bulduysanız, büyük mevcut (boyut Y grubu) almak, sonra adımları tekrarlayın 3 - Y - 5 X = X ile

Edit: yana ben burada soruları ilk serbest tüm first free seat and the count of adjacent koltuk dönecek bir SQL deyimi yanlış var. Ücretsiz koltuk büyük sayımları önce gelir.

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

Yani örneğin o dönecektir:

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

Sizin istek ve artık sadece ücretsiz koltuk sayısı üzerinde bir koşul eklemek, böylece ekleme 3 koltuk istiyorsanız free>=3 bunu yapacak sığabilecek ilk sequencial koltukta sadece istiyorsanız:

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

bu irade çıktı:

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