我有一个数据库(MySQL),其中包含一个包含日期范围(作为startdate和enddate)和rate字段的表。日期范围意味着不同的季节(低,高等)。这种情况是一个人在酒店办理入住手续,他的逗留时间是两个季节。示例数据如下所示:
SeasonName SartDate EndDate Rate
Low 01-01-2007 30-04-2007 100.00
High 01-05-2007 31-08-2007 150.00
Peak 01-09-2007 31-12-2007 200.00
客户的登记日期为29-04-2007,退房日期为03-05-2007。我需要计算每个季节的确切夜数,并计算总金额。
IDE是VB6。任何帮助将非常感激。
由于
汤姆
感谢您的回复。我需要SQL来提取信息。至于日期有效期,我们假设费率适用于午夜(00:00)。希望我澄清了。
汤姆
答案 0 :(得分:8)
在酒店工作并编写了预订系统,到目前为止每小时的时间是无关紧要的 结算。一切都是晚上充电。 (除非您打算经营一个按小时收费的地方!;-))办理登机手续和退房手续是运营方面的考虑因素。
如果您真的想要编写真实的预订系统,请不要使用存储过程。 它违背了建立数据库的目的。
另外,写出这样的日期是2007-04-29真的很棒,因为不是每个人都来自同一个地方,这是一个国际标准。另请注意,如果您将其转换为字符串,它仍将正确排序!
你需要制作一个calandar表,因为MySQL在内置函数中没有这样做。 此程序将为您建立日期。
drop table if exists calendar;
create table calendar
(
date_ date primary key
);
drop procedure fill_calendar;
delimiter $$
create procedure fill_calendar(start_date date, end_date date)
begin
declare date_ date;
set date_=start_date;
while date_ < end_date do
insert into calendar values(date_);
set date_ = adddate(date_, interval 1 day);
end while;
end $$
delimiter ;
call fill_calendar('2007-1-1', '2007-12-31');
来自:http://www.ehow.com/how_7571744_mysql-calendar-tutorial.html
drop table if exists rates;
create table rates
(
season varchar(100) primary key,
start_date date references calendar(date_),
end_date date references calendar(date_),
rate float
);
insert into rates values ('Low', '2007-01-01', '2007-04-30', 100.00);
insert into rates values ('High', '2007-05-01', '2007-08-31', 150.00);
insert into rates values ('Peak', '2007-09-01', '2007-12-21', 200.00);
select * from rates;
season start_date end_date rate
Low 2007-01-01 2007-04-30 100
High 2007-05-01 2007-08-31 150
Peak 2007-09-01 2007-12-21 200
我将忽略你在问题中给出的日期,并假设客户没有及时倒退。
select
date_, rate
from calendar
join rates
on date_ >= start_date and date_ <= end_date
where date_ between '2007-04-29' and '2007-5-01'
;
date_ rate
2007-04-29 100
2007-04-30 100
2007-05-01 150
select
sum(rate)
from calendar
join rates
on date_ >= start_date and date_ <= end_date
where date_ between '2007-04-29' and '2007-5-01'
sum(rate)
350
而且,正如您所看到的,sql非常简洁易读,无需借助函数或过程。这将能够正确扩展并处理更复杂的问题。此外,它还支持使用参照检查,因为数据是基于表格的。
答案 1 :(得分:1)
我使用DATEDIFF函数来了解两个日期之间的天数。但由于此函数返回的日数不包括最后一天(例如DATEDIFF(d, '2007-04-29', '2007-04-30')
返回1而不是2),我使用了这样的费率表:
SeasonName StartDate EndDate Rate
Low 01-01-2007 01-05-2007 100.00
High 01-05-2007 01-09-2007 150.00
Peak 01-09-2007 01-01-2008 200.00
这是我使用的查询。两个SELECT的内部根据季节(季节的结束日期或结束日期之前的日期)计算客户住宿的有效结束日期。
我使用02-05-2007作为客户的逗留结束日期而不是03-05-2007,因为通常客户在退房当天不付款。
SELECT SeasonName, DATEDIFF(d, '2007-04-29', EffectiveEndDate) as NumberOfDays, Rate
FROM (
SELECT SeasonName,
CASE
WHEN EndDate < '2007-05-02' THEN EndDate
ELSE '2007-05-02'
END AS EffectiveEndDate,
Rate
FROM HotelRate
WHERE (StartDate <= '2007-04-29' and EndDate > '2007-04-29')
or (StartDate <= '2007-05-02' and EndDate > '2007-05-02')
) as SubSelect
这给了我这个结果:
SeasonName NumberOfDays Rate
Low 2 100.00
High 3 150.00
我希望它有所帮助:)
答案 2 :(得分:0)
免责声明:这不是最有效的,但它更清晰,如果您将数据列表缓存在一个数组中,性能损失将毫无意义。
Dim numberOfDays As Integer, i As Integer
Dim CheckInDate As Date, CheckOutDate As Date, CurrDate As Date
Dim TotalRate As Currency
TotalRate = 0
CheckInDate = DateSerial(2007, 4, 29)
CheckOutDate = DateSerial(2007, 5, 3)
''// -1 asumming the last day is checkout day
numberOfDays = DateDiff("d", CheckInDate, CheckOutDate) - 1
For i = 0 To numberOfDays
CurrDate = DateAdd("d", i, CheckInDate)
TotalRate = TotalRate + CalculateRateForDay(CurrDate)
Next
答案 3 :(得分:0)
SELECT S1.client_ID, H1.Rate, C1.dt
FROM HotelRates AS H1
INNER JOIN Calendar AS C1
ON C1.dt BETWEEN H1.SartDate AND H1.EndDate
INNER JOIN Stays AS S1
ON C1.dt >= check_in_date AND
C1.dt < check_out_date;