5

空のbookingIdを持つレコードを抽出し、予約されていない最大日数を(最初の空き日から)取り戻したいと思います。期待される結果は次のとおりです。

id = 1, 2013-08-03, 7 days free
id = 1, 2013-08-24, 7 days free
id = 2, 2013-08-07, 10 days free
id = 2, 2013-08-24, 7 days free

最良の方法は、空き時間枠もクエリできる場合です。たとえば、1,2,3,4,5,6,7..14.. の空き日をクエリします。これは私のソースデータの例です:

id      bookingDate    bookingId
--------------------------------
1        2013-08-03        0
1        2013-08-04        0
1        2013-08-05        0
1        2013-08-06        0
1        2013-08-07        0
1        2013-08-08        0
1        2013-08-09        0
1        2013-08-10        112
1        2013-08-11        112
1        2013-08-12        112
1        2013-08-13        112
1        2013-08-14        112
1        2013-08-15        112
1        2013-08-16        112
1        2013-08-17        112
1        2013-08-18        112
1        2013-08-19        112
1        2013-08-20        112
1        2013-08-21        112
1        2013-08-22        112
1        2013-08-23        112
1        2013-08-24        0
1        2013-08-25        0
1        2013-08-26        0
1        2013-08-27        0
1        2013-08-28        0
1        2013-08-29        0
1        2013-08-30        0
1        2013-08-31        0
2        2013-08-03        78
2        2013-08-04        78
2        2013-08-05        78
2        2013-08-06        78
2        2013-08-07        0
2        2013-08-08        0
2        2013-08-09        0
2        2013-08-10        0
2        2013-08-11        0
2        2013-08-12        0
2        2013-08-13        0
2        2013-08-14        0
2        2013-08-15        0
2        2013-08-16        0
2        2013-08-17        39
2        2013-08-18        39
2        2013-08-19        39
2        2013-08-20        39
2        2013-08-21        39
2        2013-08-22        39
2        2013-08-23        39
2        2013-08-24        0
2        2013-08-25        0
2        2013-08-26        0
2        2013-08-27        0
2        2013-08-28        0
2        2013-08-29        0
2        2013-08-30        0
2        2013-08-31        0

より良いデータ構造について誰かが良いアイデアを持っている場合は、実装を試みることができます。データベースはまだ構築中です:-)

編集:

CREATE TABLE IF NOT EXISTS `pricesBookings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `baseId` int(11) NOT NULL,
  `bookingDate` date NOT NULL,
  `bookingId` int(11) NOT NULL,
  `price` decimal(10,2) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `baseId` (`baseId`,`bookingDate`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;
4

3 に答える 3

4

これにより、正しい結果が得られるはずです。

select
  id,
  min(startDate) as startFreeDate,
  count(*) - (endDate is null) numFreeDays
from (
  select
    pb1.id,
    pb1.bookingDate startDate,
    min(pb2.bookingDate) endDate
  from
    pricesBookings pb1 left join pricesBookings pb2
    on pb1.id=pb2.id
       and pb2.price>0
       and pb2.bookingDate>pb1.bookingDate
  where
    pb1.price=0
  group by
    pb1.id,
    pb1.bookingDate
) s
group by id, endDate
order by id, startDate

ここでそれを参照してください

たとえば、14 日間の空きスロットをすべて検索する必要がある場合は、HAVING を追加できます。

group by id, endDate
having count(*) - (endDate is null) >= 14
order by id, startDate
于 2013-02-06T17:39:05.243 に答える
0

これを試してください...

select
  concat_ws(',',(concat("ID=",id)),
  min(startDate),
 (concat((count(*) - (endDate is null))," Days Free"))) as result
from (
  select
    pb1.id,
    pb1.bookingDate startDate,
    min(pb2.bookingDate) endDate
  from
    pricesBookings pb1 left join pricesBookings pb2
    on pb1.id=pb2.id
       and pb2.price>0
       and pb2.bookingDate>pb1.bookingDate
  where
    pb1.price=0
  group by
    pb1.id,
    pb1.bookingDate
) s
group by id, endDate
  order by id, startDateselect
  concat_ws(',',(concat("ID=",id)),
  min(startDate),
 (concat((count(*) - (endDate is null))," Days Free"))) as result
from (
  select
    pb1.id,
    pb1.bookingDate startDate,
    min(pb2.bookingDate) endDate
  from
    pricesBookings pb1 left join pricesBookings pb2
    on pb1.id=pb2.id
       and pb2.price>0
       and pb2.bookingDate>pb1.bookingDate
  where
    pb1.price=0
  group by
    pb1.id,
    pb1.bookingDate
) s
group by id, endDate
  order by id, startDate
于 2013-02-07T04:43:11.063 に答える
0

これで遊んだ。明らかな何かが欠けている可能性がありますが、単一のステートメントでこれを行う簡単な方法がわかりません。

しかし、私はこの厄介な方法を思いつきました。

SELECT z.baseid, z.bookingdate, 
CASE 
    WHEN j.id IS NOT NULL THEN '11+ days free'
    WHEN i.id IS NOT NULL THEN '10 days free'
    WHEN h.id IS NOT NULL THEN '9 days free'
    WHEN g.id IS NOT NULL THEN '8 days free'
    WHEN f.id IS NOT NULL THEN '7 days free'
    WHEN e.id IS NOT NULL THEN '6 days free'
    WHEN d.id IS NOT NULL THEN '5 days free'
    WHEN c.id IS NOT NULL THEN '4 days free'
    WHEN b.id IS NOT NULL THEN '3 days free'
    WHEN a.id IS NOT NULL THEN '2 days free'
    ELSE '1 day free'
END AS DaysFree
FROM pricesbookings z
INNER JOIN pricesbookings y
ON z.baseid = y.baseid AND z.bookingid = 0 AND y.bookingid != 0 AND DATE_ADD(y.bookingdate, INTERVAL 1 DAY) = z.bookingdate
LEFT JOIN pricesbookings a ON z.baseid = a.baseid AND z.bookingid = 0 AND a.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 1 DAY) = a.bookingdate
LEFT OUTER JOIN pricesbookings b ON a.baseid = b.baseid AND b.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 2 DAY) = b.bookingdate
LEFT OUTER JOIN pricesbookings c ON b.baseid = c.baseid AND c.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 3 DAY) = c.bookingdate
LEFT OUTER JOIN pricesbookings d ON c.baseid = d.baseid AND d.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 4 DAY) = d.bookingdate
LEFT OUTER JOIN pricesbookings e ON d.baseid = e.baseid AND e.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 5 DAY) = e.bookingdate
LEFT OUTER JOIN pricesbookings f ON e.baseid = f.baseid AND f.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 6 DAY) = f.bookingdate
LEFT OUTER JOIN pricesbookings g ON f.baseid = g.baseid AND g.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 7 DAY) = g.bookingdate
LEFT OUTER JOIN pricesbookings h ON g.baseid = h.baseid AND h.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 8 DAY) = h.bookingdate
LEFT OUTER JOIN pricesbookings i ON h.baseid = i.baseid AND i.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 9 DAY) = i.bookingdate
LEFT OUTER JOIN pricesbookings j ON i.baseid = j.baseid AND j.bookingid = 0 AND DATE_ADD(z.bookingdate, INTERVAL 10 DAY) = j.bookingdate
ORDER BY z.baseid, z.bookingdate

これは 11 日以上しかカウントされず (必要に応じて拡張するのは簡単ですが、事前に最大数を知る必要があります)、おそらく非常に非効率的です。

基本的に、テーブル エイリアス z は最初の日であり、テーブル エイリアス y に対して結合されて、前日が予約されたことを確認します。次に、日付に余分な日を追加して、テーブルのより多くのコピーをロードに対して LEFT JOIN します。次に、CASE ステートメントを使用して、無料の日数を得るために見つかった最大のものを確認します。

動作しますが、あなたのデータベースはそれを評価しないかもしれません!

于 2013-02-06T17:32:28.497 に答える