2013-02-06 56 views
5

我想提取具有空的bookingId的記錄並獲得最長未預訂的日期(從第一個空閒日)。預期的結果應該是:使用mysql查找與日期的差距

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; 
+0

喜ü可以給我..........創建查詢和插入查詢..........創建數據庫......我會盡我所能 –

+0

我已經在發佈之前添加了它。提前致謝。 – Stefan

回答

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 

看到它here

如果你需要搜索的所有空閒時隙,例如,14天,你可以添加HAVING:

group by id, endDate 
having count(*) - (endDate is null) >= 14 
order by id, startDate 
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聯合加載更多表格的副本,並在日期中添加額外的一天。然後使用一個CASE語句來檢查哪一個是發現給你的免費天數中最大的一個。

工程,但你的數據庫可能不會感激它!

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