我正在编写一个查询以检测重叠时间。对于房间预订系统,如果用户输入的时隙与已经存储的任何时间和时间输出重叠,则不应进行预约。我的表格结构为:
ID BOARDROOM_TYPE REQUEST_TIME USER_REQUEST SUBJECT FROM_DATE TO_DATE FROM_TIME TO_TIME
17174 Board Room 06/11/2014 1:21:00 AM User A Some Subject 11/11/2014 11/11/2014 01/11/2014 2:30:00 PM 01/11/2014 5:00:00 PM
17172 Board Room 06/11/2014 12:50:58 AM User B Meeting 11/11/2014 11/11/2014 01/11/2014 9:00:00 AM 01/11/2014 1:00:00 PM
现根据这些数据,房间预留时间为上午9点至下午1点,然后是下午2:30至下午5点。
我在同一房间内检查同一日期重叠会议时间的查询是:
select count(*) from meeting_data where not (to_time <= to_date('13:00','hh24:mi:ss') and from_time >= to_date('14:00','hh24:mi:ss')) and trunc(from_date) = trunc(Sysdate) and boardroom_type = 'Board Room' and deleted = 'N'
当timeIn = 13:00且timeOut = 14:00时,它返回2,如果count > 0
,则不应插入数据。到目前为止工作正常。
问题在于,当我输入重叠时间时,如timeIn = 09:00 timeOut = 14:00
,它仍然会提供2,并且自count > 0
后插入即使已经在此时段中进行预订(ID = 17172)。
我的查询出错了什么?
答案 0 :(得分:2)
select count(*) from meeting_data
where NOT (
to_date(to_char(to_time, 'YYYYMMDD') || '13:00','YYYYMMDDhh24:mi')
not between from_time and to_time
and to_date(to_char(to_time, 'YYYYMMDD') || '14:00','YYYYMMDDhh24:mi')
not between from_time and to_time
and to_time not between to_date(to_char(to_time, 'YYYYMMDD') || '13:00','YYYYMMDDhh24:mi')
and to_date(to_char(to_time, 'YYYYMMDD') || '14:00','YYYYMMDDhh24:mi')
)
and from_date between trunc(Sysdate) and trunc(Sysdate+1) -1/24/60/60
and boardroom_type = 'Board Room' and deleted = 'N';
前三个条件检查是否与[from_date,to_date]没有交叉点+检查[from_date,to_date]是否不在所需的时间间隔内
您的查询中也出现了问题:
The default date values are determined as follows:
- The year is the current year, as returned by SYSDATE.
- The month is the current month, as returned by SYSDATE.
- The day is 01 (the first day of the month).
- The hour, minute, and second are all 0.
因此to_time <= to_date('13:00','hh24:mi:ss')
可能会给您带来不受欢迎的结果,具体取决于您执行此比较的日期。
使用trunc(from_date) = trunc(Sysdate)
进行微小更改我删除了列上的一个函数(这是一个很好的索引候选者)
如果间隔[09:00 - 13:00]和[13:00 - 14:00]被认为没有相交,那么您可以使用不严格的比较:
更改
some_date not between from_time and to_time
要
some_date <= from_time or some_date >= to_time
以下是修改过的查询:
select count(*) from meeting_data
where (to_date(to_char(from_date, 'YYYYMMDD') || '13:00','YYYYMMDDhh24:mi') > from_date
and to_date(to_char(from_date, 'YYYYMMDD') || '13:00','YYYYMMDDhh24:mi') < to_date
or to_date(to_char(from_date, 'YYYYMMDD') || '14:00','YYYYMMDDhh24:mi') > from_date
and to_date(to_char(to_time, 'YYYYMMDD') || '14:00','YYYYMMDDhh24:mi') < to_date
or to_time > to_date(to_char(to_time, 'YYYYMMDD') || '13:00','YYYYMMDDhh24:mi')
and to_time < to_date(to_char(to_time, 'YYYYMMDD') || '14:00','YYYYMMDDhh24:mi')
)
and from_date between trunc(Sysdate) and trunc(Sysdate+1) -1/24/60/60
and boardroom_type = 'Board Room' and deleted = 'N';
答案 1 :(得分:0)
据我了解您的问题,您需要检查用户输入的数据库值。所以我认为存储过程是这里的方式。您可以将用户输入的值传递给SP,并且检查时间是否重叠。
CREATE OR REPLACE PROCEDURE check_date_clash (
p_start_date IN DATE,
p_end_date IN DATE,
l_count OUT NUMBER
)
AS
BEGIN
SELECT COUNT(*)
INTO l_count
FROM meeting_data
WHERE from_time <= p_end_date
AND to_time >= p_start_date
AND trunc(from_date) = trunc(Sysdate)
AND boardroom_type = 'Board Room'
AND deleted = 'N';
END check_date_clash;
/
这将使用用户输入的时间段计算重叠记录并返回计数。
答案 2 :(得分:0)
为什么不使用交叉连接,它将获得现有时间轴之间的记录 SELECT COUNT(*)FROM MEETING_DATA A,MEETING_DATA B WHERE A.FROM_TIME&gt; B.FROM_TIME和A.FROM_TIME&lt; B.TO_TIME AND ......;