我在Delphi 2010中使用ADO数据库(TADOQuery)。
目的地是找到可用的房间并显示小型INN的房价。
t_room
coderoom as string
coderoomtype as string
t_typeroom
coderoomtype as string
nameroomtype as string
priceroomtype as number
t_trans
datetrans as date
codepoeple as string
coderoom as string
dateintrans as date -> date check in
dateouttrans as date -> date check out
目前,我使用下面的查询来显示房价。
SELECT
t_room.coderoom, t_room.coderoomtype, t_roomtype.coderoomtype,
t_roomtype.nameroomtype, t_roomtype.priceroomtype
FROM
t_room
INNER JOIN
t_roomtype ON t_room.coderoomtype = t_roomtype.coderoomtype
ORDER BY
t_room.coderoom ASC;
并设法显示:(在Delphi 2010中的ADOQuery1和DBGrid1中)
coderoom | nameroomtype | priceroomtype
----------------------------------------
101 | VIP | 20
102 | VIP | 20
103 | Standart | 10
104 | Standart | 10
105 | Standart | 10
106 | Standart | 10
我想要做的是如何在t_trans中显示尚未预订或尚未检查的代码室? (具体日期)
可能如下所示(使用NOT IN
运算符):
SELECT
t_room.coderoom, t_room.coderoomtype, t_room.notesroom,
t_roomtype.coderoomtype, t_roomtype.nameroomtype, t_roomtype.priceroomtype
FROM
t_room
INNER JOIN
t_roomtype ON t_room.coderoomtype = t_roomtype.coderoomtype
WHERE
t_room.coderoom NOT IN (SELECT *
FROM t_trans
WHERE [current book/checkin/out date not between dateintrans and dateoutrans]
ORDER BY coderoom ASC)
ORDER BY
t_room.coderoom ASC;
问题是如何在t_trans.datein和t_trans.dateout之间找到未预订的可用房间?
我添加了一些文件,以便于理解我想要执行的操作:http://sidhiciang.com/myfiles/TRIAL%20Available%20Rooms.rar
当我使用下面的代码时,返回错误:$7701C41F - Exception class EOleException with message "You have writen a subquest that can return more than one field without using EXISTS reserved word in the main query's FROM clause. Revise the SELECT statement of the subquery to request only one field."
代码是:
AQRoomAvailable1.SQL.Text := 'SELECT t_room.coderoom, t_room.coderoomtype, t_room.notesroom, t_roomtype.coderoomtype, t_roomtype.nameroomtype, t_roomtype.priceroomtype ';
AQRoomAvailable1.SQL.Text := AQRoomAvailable1.SQL.Text + 'FROM t_room INNER JOIN t_roomtype ON t_room.coderoomtype = t_roomtype.coderoomtype WHERE t_room.coderoom ';
AQRoomAvailable1.SQL.Text := AQRoomAvailable1.SQL.Text + 'NOT IN (SELECT * FROM t_trans x WHERE x.coderoom = t_room.coderoom AND ( (x.dateintrans BETWEEN ' + DateToStr(dtpDateIn1.Date) + ' AND ' + DateToStr(dtpDateOut1.Date) + ' ) ';
AQRoomAvailable1.SQL.Text := AQRoomAvailable1.SQL.Text + 'OR (x.dateouttrans BETWEEN ' + DateToStr(dtpDateIn1.Date) + ' AND ' + DateToStr(dtpDateOut1.Date) + ' ) ';
AQRoomAvailable1.SQL.Text := AQRoomAvailable1.SQL.Text + 'OR (' + DateToStr(dtpDateIn1.Date) + ' BETWEEN x.dateintrans AND x.dateouttrans) ) )';
我已经阅读了下面的链接,但没有找到答案并且更加困惑....
check availability of a room with SQL
mysql hotel room availability
listing rooms available[hotel reservation]
query for available rooms in hotel reservation
Select available rooms
selecting room type on room availabilty subquery
Room Booking Query
Room booking sql query
SQL Scheduling - Select All Rooms Available for Given Date Range
SQL Inner-join with 3 tables?
How can I join multiple SQL tables using the IDs?
SQL Query NOT Between Two Dates
答案 0 :(得分:4)
SQL似乎不是这个问题的主要问题。要查找所有研磨范围,您必须区分4种情况,其中案例2是案例1或3的特例。
如果你想使用参数进行查询,你应该根据数据库引擎使用参数,如果你能够在SQL中声明变量,以避免使用比所需更多的参数。一个示例SQL可能看起来像(根据您的结束和开始日期的方式,您可能需要在参数中添加/减去offest):
Declare @SW datetime
Declare @EW datetime
Select @SW=:SW
Select @EW=:EW
SELECT
t_room.coderoom, t_room.coderoomtype,
t_roomtype.coderoomtype, t_roomtype.nameroomtype, t_roomtype.priceroomtype
FROM
t_room
INNER JOIN
t_roomtype ON t_room.coderoomtype = t_roomtype.coderoomtype
WHERE
t_room.coderoom NOT IN (SELECT x.coderoom
FROM t_trans x
WHERE
(x.dateouttrans between @SW and @EW )
OR (x.dateintrans between @SW and @EW )
OR (@SW between x.dateintrans and x.dateouttrans)
)
ORDER BY
t_room.coderoom ASC;
编辑回复评论
由于Access无法使用本地变量,因此您必须使用5个参数,不应尝试创建不带参数的SQL。 AQRoomAvailable1的SQL看起来像:
SELECT
t_room.coderoom, t_room.coderoomtype,
t_roomtype.coderoomtype, t_roomtype.nameroomtype, t_roomtype.priceroomtype
FROM
t_room
INNER JOIN
t_roomtype ON t_room.coderoomtype = t_roomtype.coderoomtype
WHERE
t_room.coderoom NOT IN (SELECT x.coderoom
FROM t_trans x where
(x.dateouttrans between :SW and :EW )
OR (x.dateintrans between :SW1 and :EW1 )
OR (:SW2 between x.dateintrans and x.dateouttrans)
)
ORDER BY
t_room.coderoom ASC;
将参数的数据类型更改为ftDateTime:
将您的Action actRoomCheckIn1更改为:
procedure TFMain.actRoomCheckIn1Execute(Sender: TObject);
begin
if (dtpDateOut1.Date >= dtpDateIn1.Date) then
begin
AQRoomAvailable1.Close;
AQRoomAvailable1.Parameters.ParamByName('SW').Value := dtpDateIn1.Date;
AQRoomAvailable1.Parameters.ParamByName('EW').Value := dtpDateOut1.Date;
AQRoomAvailable1.Parameters.ParamByName('SW1').Value := dtpDateIn1.Date;
AQRoomAvailable1.Parameters.ParamByName('EW1').Value := dtpDateOut1.Date;
AQRoomAvailable1.Parameters.ParamByName('SW2').Value := dtpDateIn1.Date;
AQRoomAvailable1.Open;
end
else
begin
AQRoomAvailable1.Active := False;
end;
end;
答案 1 :(得分:1)
两个观察结果:
如果dateintrans是预订的开始,而dateouttrans就是结束,那么您需要的查询可能是以下
SELECT t_room.coderoom
from t_room
where not exists (select 1 from t_trans
where t_trans.coderoom = t_room.coderoom
and t_trans.dateintrrans >= :p1
and t_trans.dateouttrans <= :p1)
:p1是您要检查的日期。