2

我正在尝试编写两个 SQL 语句。第一个将在晚上 11 点到早上 6 点之间显示,第二个将在晚上 11 点到早上 6 点之间显示 NOT。

我想弄清楚的是,当我说不在之间

WHERE TO_CHAR(MOPACTIVITY.MOPSTART, 'hh24:mi') NOT BETWEEN '23:00' AND '06:00'

我得到了“23:00”和“06:00”之间的记录。这似乎与我在 SQL 中要求的相反。那是怎么回事?

4

3 回答 3

3

一种解决方案是使用'SSSSS' 格式掩码。它显示午夜后的秒数,非常适合处理时间,而与日期元素无关。

06:00 至 23:00 之间是

select * from t23
where to_number(to_char(some_date_coll, 'SSSSS')) is between (6*60*24) and (23*60*24);

23:00 至 06:00 之间是

select * from t23
where to_number(to_char(some_date_coll, 'SSSSS')) < (6*60*24) 
     or to_number(to_char(some_date_coll, 'SSSSS')) > (23*60*24);

或者在第一个查询中使用 NOT BETWEEN。

我将算术保留为扩展形式,因为它比硬编码的秒数更容易理解(和修改)。

关于围绕索引列包装函数的性能影响的常见警告适用于此处。

于 2013-07-05T16:13:16.373 回答
0

我不确定您对“BETWEEN”的使用是否符合您的意图。我担心的是“介于”是“包含”两个指定值。通常在过滤日期时,您需要一个不包括至少一个边界的开放式间隔。

例如,在您的问题中, between 将检索/省略 06:00 和 23:00 分钟。如下所示,以说明我的观点。

使用“测试数据设置”下面的部分,我构建了一个边缘案例测试数据集。

这是两个查询的输出:

查询 BETWEEN 06 和 23

select 
  m.mopstart
from 
  mopactivity m
where 1=1
  and to_char(m.mopstart, 'HH24:MI') between '06:00' and '23:00'
order by 
  m.mopstart
;

10-SEP-02 06.00.00.000000000 AM
10-SEP-02 06.01.00.000000000 AM
10-SEP-02 10.59.00.000000000 PM
10-SEP-02 11.00.00.000000000 PM    <-- Did you really want 23:00 record here?

查询 NOT BETWEEN 06 和 23

select 
  m.mopstart
from 
  mopactivity m
where 1=1
  and to_char(m.mopstart, 'HH24:MI') NOT between '06:00' and '23:00'
order by 
  m.mopstart
;

10-SEP-02 12.00.00.000000000 AM
10-SEP-02 05.59.00.000000000 AM
10-SEP-02 11.01.00.000000000 PM

测试数据设置 ::

drop table mopactivity
;

create table mopactivity
(
  mopstart timestamp  NOT NULL
)
;

insert into mopactivity
values( 
  TO_TIMESTAMP ('10-Sep-02 22:59', 'DD-Mon-RR HH24:MI') 
)
;
insert into mopactivity
values( 
  TO_TIMESTAMP ('10-Sep-02 23:00', 'DD-Mon-RR HH24:MI') 
)
;
insert into mopactivity
values( 
  TO_TIMESTAMP ('10-Sep-02 23:01', 'DD-Mon-RR HH24:MI') 
)
;
insert into mopactivity
values( 
  TO_TIMESTAMP ('10-Sep-02 05:59', 'DD-Mon-RR HH24:MI') 
)
;
insert into mopactivity
values( 
  TO_TIMESTAMP ('10-Sep-02 06:00', 'DD-Mon-RR HH24:MI') 
)
;
insert into mopactivity
values( 
  TO_TIMESTAMP ('10-Sep-02 06:01', 'DD-Mon-RR HH24:MI') 
)
;
insert into mopactivity
values( 
  TO_TIMESTAMP ('10-Sep-02 00:00', 'DD-Mon-RR HH24:MI') 
)
;

commit
;
于 2013-07-05T16:41:43.403 回答
0

你想要的代码是:

WHERE TO_CHAR(MOPACTIVITY.MOPSTART, 'hh24:mi') BETWEEN 'o6:00' AND '23:00'

和:

WHERE TO_CHAR(MOPACTIVITY.MOPSTART, 'hh24:mi') not BETWEEN '06:00' AND '23:00'

betweenand运算符总是假设第not between一个界限小于第二个界限。所以没有任何匹配:

where x between 2 and 1

一切都匹配:

where x not between 2 and 1

另一种写法是使用小时:

WHERE hour(MOPACTIVITY.MOPSTART) between 6 and 23 - 1

第二个是:

where hour(MOPACTIVITY.MOPSTART) NOT BETWEEN 6 and 23 - 1

hour()使用和您的配方之间存在差异。例如23:00:106-23 的时间与您的时间匹配,但与此版本不匹配。

于 2013-07-05T16:45:46.600 回答