我想提取具有空的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;
答案 0 :(得分: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
答案 1 :(得分: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 JOINs加载表的更多副本,每个日期都添加一天。然后使用CASE语句检查哪个是最大的,可以免费获得天数。
可以使用,但您的数据库可能不会欣赏它!
答案 2 :(得分: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