不同日期的时间范围内的最小/最大值

时间:2015-03-16 04:45:17

标签: sql oracle

我有一张这样的桌子:

[absence_card_no]  [clocking_time]  
040000654           2014-12-04 07:50:00  
160300101           2014-12-13 16:47:00  
160300046           2014-12-27 13:31:00    
160300133           2015-01-05 07:55:00  
160300081           2014-12-27 13:04:00  
020001670           2014-12-15 17:35:00  
020400055           2014-10-27 07:37:00  
160300146           2014-12-27 17:22:00  
020001311           2014-12-27 15:21:00  

我需要在每天的时间范围内搜索最小值或最大值,并使用此查询:

select NC.ABSENCE_CARD_NO, TRUNC(NC.CLOCKING_TIME) daydate, min(NC.CLOCKING_TIME)  
from nna_clocking_tbl nc  
where clocking_time BETWEEN TO_DATE(TO_CHAR(clocking_time,'DD-MM-YYYY')||'16:00:00','DD-MM-YYYY HH24:MI:SS')   
AND TO_DATE(TO_CHAR(clocking_time,'DD-MM-YYYY')||'23:59:00','DD-MM-YYYY HH24:MI:SS')  
group by NC.ABSENCE_CARD_NO, CLOCKING_TIME  

到目前为止,如果范围在一天16:00-23:59之间,它的工作正常,但我需要在不同的日期,例如星期一22:00到星期一02:00。我尝试在计时时间中通过substract-1修改'where'子句:

clocking_time BETWEEN TO_DATE(TO_CHAR(clocking_time-1,'DD-MM-YYYY')||'22:00:00','DD-MM-YYYY HH24:MI:SS')   
AND TO_DATE(TO_CHAR(clocking_time,'DD-MM-YYYY')||'02:00:00','DD-MM-YYYY HH24:MI:SS')

但它没有按预期工作:( 注意:oracle 11.x

编辑:
很抱歉不清楚,我正在寻找的是在的时间范围内的最小值,例如22:00到02:00(第二天)。我的上述查询仅在一天内(00:00-24:00)范围内有效... 我需要在第二天包含范围内。 如果where子句:

clocking_time BETWEEN TO_DATE(TO_CHAR(clocking_time-1,'DD-MM-YYYY')||'22:00:00','DD-MM-YYYY HH24:MI:SS') 
                             AND TO_DATE(TO_CHAR(clocking_time,'DD-MM-YYYY')||'01:59:00','DD-MM-YYYY HH24:MI:SS')

它仅显示00:00-02:00

的结果
clocking_time BETWEEN TO_DATE(TO_CHAR(clocking_time,'DD-MM-YYYY')||'22:00:00','DD-MM-YYYY HH24:MI:SS') 
                             AND TO_DATE(TO_CHAR(clocking_time+1,'DD-MM-YYYY')||'01:59:00','DD-MM-YYYY HH24:MI:SS')

它只显示22:00-23:59

的结果

2 个答案:

答案 0 :(得分:1)

您的GROUP BY子句在您的第一个查询中似乎不正确。如果同一天的卡号有多个clocking_time,您将同时得到结果。您应该按trunc(clocking_time)分组。

SQL Fiddle Oracle 11g R2架构设置

create table myt(
absence_card_no varchar2(10),
clocking_time date
);

insert into myt values('040000654', to_date('2014-12-04 07:50:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('160300101', to_date('2014-12-13 16:47:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('160300046', to_date('2014-12-27 13:31:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('160300081', to_date('2014-12-27 13:04:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('020001670', to_date('2014-12-15 17:35:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('020400055', to_date('2014-10-27 07:37:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('160300146', to_date('2014-12-27 17:22:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('160300133', to_date('2015-01-05 16:21:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('160300133', to_date('2015-01-05 22:55:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('020400055', to_date('2015-01-06 01:55:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('020400055', to_date('2015-01-05 01:55:00','yyyy-mm-dd hh24:mi:ss'));
insert into myt values('020400055', to_date('2015-01-05 22:55:00','yyyy-mm-dd hh24:mi:ss'));

查询1

select 
absence_card_no, 
trunc(clocking_time) daydate, 
min(clocking_time)  
from myt
where clocking_time between to_date(to_char(clocking_time,'dd-mm-yyyy')||'16:00:00','dd-mm-yyyy hh24:mi:ss')   
and to_date(to_char(clocking_time,'dd-mm-yyyy')||'23:59:00','dd-mm-yyyy hh24:mi:ss')  
group by absence_card_no, trunc(clocking_time)

<强> Results

| ABSENCE_CARD_NO |                    DAYDATE |         MIN(CLOCKING_TIME) |
|-----------------|----------------------------|----------------------------|
|       160300101 | December, 13 2014 00:00:00 | December, 13 2014 16:47:00 |
|       160300146 | December, 27 2014 00:00:00 | December, 27 2014 17:22:00 |
|       020001670 | December, 15 2014 00:00:00 | December, 15 2014 17:35:00 |
|       020400055 |  January, 05 2015 00:00:00 |  January, 05 2015 22:55:00 |
|       160300133 |  January, 05 2015 00:00:00 |  January, 05 2015 16:21:00 |

如果您想要包含两天的范围,则无法使用BETWEEN并给出时间范围。相反,您可以使用NOT BETWEEN 02:00 and 22:00。 或者您可以使用clocking_time >= 22:00 or clocking_time < 02:00

查询2

select 
absence_card_no, 
trunc(clocking_time) daydate, 
min(clocking_time)  
from myt
where clocking_time >= to_date(to_char(clocking_time,'dd-mm-yyyy')||'22:00:00','dd-mm-yyyy hh24:mi:ss')   
or clocking_time < to_date(to_char(clocking_time,'dd-mm-yyyy')||'02:00:00','dd-mm-yyyy hh24:mi:ss')  
group by absence_card_no, trunc(clocking_time)

<强> Results

| ABSENCE_CARD_NO |                   DAYDATE |        MIN(CLOCKING_TIME) |
|-----------------|---------------------------|---------------------------|
|       020400055 | January, 05 2015 00:00:00 | January, 05 2015 01:55:00 |
|       020400055 | January, 06 2015 00:00:00 | January, 06 2015 01:55:00 |
|       160300133 | January, 05 2015 00:00:00 | January, 05 2015 22:55:00 |

但是,这仍然不会给你正确的结果。您按trunc(clocking_time)进行分组。如果它延长到两天,这不会考虑范围。 由于您的范围从第2天延长到第二天,因此简单的事情就是按trunc(clocking_time - interval '2' hour)进行分组。

查询3

select 
absence_card_no, 
trunc(clocking_time - interval '2' hour) daydate, 
min(clocking_time)  
from myt
where clocking_time >= to_date(to_char(clocking_time,'dd-mm-yyyy')||'22:00:00','dd-mm-yyyy hh24:mi:ss')   
or clocking_time < to_date(to_char(clocking_time,'dd-mm-yyyy')||'02:00:00','dd-mm-yyyy hh24:mi:ss')  
group by absence_card_no, trunc(clocking_time - interval '2' hour)

<强> Results

| ABSENCE_CARD_NO |                   DAYDATE |        MIN(CLOCKING_TIME) |
|-----------------|---------------------------|---------------------------|
|       020400055 | January, 04 2015 00:00:00 | January, 05 2015 01:55:00 |
|       020400055 | January, 05 2015 00:00:00 | January, 05 2015 22:55:00 |
|       160300133 | January, 05 2015 00:00:00 | January, 05 2015 22:55:00 |

答案 1 :(得分:0)

这是答案吗?

select distinct CONVERT(VARCHAR(10),clocking_time,10) as [Date],
b.absence_card_no as min_absence_card, 
c.absence_card_no as max_absence_card
from absence a
inner join 
(
select CONVERT(VARCHAR(10),clocking_time,10) as min_clocking_time, 
absence_card_no 
from absence 
where clocking_time in ( 
    select  Min(clocking_time) as min_clocking_time
    from absence
    GROUP BY CONVERT(VARCHAR(10),clocking_time,10)
 )
) b 
on CONVERT(VARCHAR(10),a.clocking_time,10) = b.min_clocking_time
inner join 
(
   select CONVERT(VARCHAR(10),clocking_time,10) as max_clocking_time, 
   absence_card_no 
   from absence
    where clocking_time in ( 
        select Max(clocking_time) as max_clocking_time
        from absence
        GROUP BY CONVERT(VARCHAR(10),clocking_time,10)
    )
) c
on CONVERT(VARCHAR(10),a.clocking_time,10) = c.max_clocking_time

我在SQL SERVER中做过它可能需要为ORACLE进行更多转换