Reputation: 113
i have a table like this:
[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
i need to search min or max value within a time range for each day, and i use this query:
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
so far it's working fine if the range within one day 16:00-23:59, but i need the range to be in different day for example 22:00 sunday until 02:00 monday. I try to modify 'where' clause by substract-1 in clocking time:
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')
but it's not working as expected :( note: oracle 11.x
edit:
sorry for being unclear, what i'm looking for is min value within a time range for example 22:00 until 02:00 (next day). My query above only works if the range within one day (00:00-24:00)...i need to include next day in the range.
if the where clause:
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')
it only display result from 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')
it only display result from 22:00-23:59
Upvotes: 1
Views: 992
Reputation: 10525
Your GROUP BY clause seems incorrect in your first query. If there are more than one clocking_time for a card number on same day, you will get both in your result. You should group by trunc(clocking_time)
.
SQL Fiddle Oracle 11g R2 Schema Setup:
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'));
Query 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)
| 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 |
If you want to have range that includes two days, you cant use BETWEEN and give the time range. Instead you can use NOT BETWEEN 02:00 and 22:00
.
Or you can use clocking_time >= 22:00 or clocking_time < 02:00
.
Query 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)
| 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 |
But still, this wont give you the correct result. You are grouping by trunc(clocking_time)
. This wont consider the range if it extends to two days.
Since your range extends 2 hours in to next day, simple thing is to group by trunc(clocking_time - interval '2' hour)
.
Query 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)
| 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 |
Upvotes: 1
Reputation: 113
Is this the answer?
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
I did it in SQL SERVER maybe it needs some more conversion for ORACLE
Upvotes: 0