Reputation: 242
Hi i'm trying to count the total late remark per day between two dates inputs by the user.
for example:
ID NAME DATE_TIME REMARKS
1 Aa 2020-01-18 09:57:56 LATE
2 Aa 2020-01-18 10:57:56 LATE
3 Aa 2020-01-19 06:52:56
4 Aa 2020-01-19 09:57:56 LATE
5 Aa 2020-01-19 09:57:56 LATE
6 Aa 2020-01-21 09:57:56 Late
Expected result.
NAME DATE count
Aa 2020-01-18 2
Aa 2020-01-19 2
Aa 2020-01-20 0
Aa 2020-01-21 1
The Data type of DATE_TIME is varhcar2
this is my attemp but i dont know how to achive it.
Select Count(REMARKS) countBT from TBLACCESSLOGS WHERE To_date(DATE_TIME,'YYYY-MM-DD') between To_date('2020-02-18','YYYY-MM-DD') and To_date('2020-02-20','YYYY-MM-DD')
and i get error date format picture ends before converting entire input string
pointing on DATE_TIME
as i execute.
Hope someone help me with this. Thank you in advance
Upvotes: 0
Views: 63
Reputation: 476
Try this ..
SQL> select * from late_remarks;
ID NAME DATE_TIME REMARKS
-- -- ------------------- ----
1 Aa 2020-01-18 09:57:56 LATE
2 Aa 2020-01-18 10:57:56 LATE
3 Aa 2020-01-19 06:52:56
4 Aa 2020-01-19 09:57:56 LATE
5 Aa 2020-01-19 09:57:56 LATE
6 Aa 2020-01-21 09:57:56 LATE
6 rows selected.
SQL> with dates as (
2 select to_date('17-01-2020', 'DD-MM-YYYY') + level "DATE"
3 from dual
4 connect by level <= (to_date('21-01-2020', 'DD-MM-YYYY') - to_date('17-01-2020', 'DD-MM-YYYY'))
5 )
6 select 'Aa' name, d."DATE", count(lr.remarks) count from dates d
7 left outer join late_remarks lr
8 on d."DATE" = trunc(to_timestamp (lr.date_time, 'YYYY-MM-DD HH24:MI:SS'))
9 group by d."DATE"
10 order by d."DATE";
NAME DATE COUNT
-- --------- ----------
Aa 18-JAN-20 2
Aa 19-JAN-20 2
Aa 20-JAN-20 0
Aa 21-JAN-20 1
.. assuming name to be constant
Upvotes: 0
Reputation: 14934
Since you face the prospect that there may be missing dates within the range your looking for you need to generate an entry for each date in that range. You the join those dates with your table, counting the number of remarks column.
with date_parms as
(select to_date('&Start_Date','yyyy-mm-dd') start_date
, to_date('&End_Date','yyyy-mm-dd') end_date
from dual
)
, date_list as
(select start_date+lev-1 t_date
from date_parms
, ( select level lev
from dual
connect by level <= (select end_date - start_date + 1
from date_parms
)
)
)
select t_date "Date"
, name
, count(*) "Num Late"
from date_list dl
left join lates l on trunc(l.date_time) = dl.t_date and lower(l.remark) = 'late'
where 1=1 --lower(l.remark) = 'late'
group by trunc(t_time), name;
Note. Once the initial parameters (start and end dates) are converted to from strings to dates no further date-string manipulation is required.
Upvotes: 3
Reputation: 2015
Completely edited; this is a multi-step process, the real important SQL logic is in "THE_GOODS". THe generation of days is in "DAYS" and I took that from here: https://www.zetetic.net/blog/2009/2/12/generating-a-sequential-date-series-in-oracle.html -- I don't understand it much more than ctl-c/ctl-v. "PERMS" makes the permutation of dates/names, then that is left-joined to THE_GOODS to get the counts. So for each combo of user and dates in range you get one row, and the count from THE_GOODS, or zero if there's no matching row.
to fiddle with it: http://sqlfiddle.com/#!4/42618/8
WITH DAYS AS
(SELECT TO_CHAR(TRUNC(TO_DATE('01-JAN-2020') + ROWNUM - 1, 'DD'), 'YYYY-MM-DD') AS ADAY
FROM (
SELECT ROWNUM FROM (
SELECT 1 FROM DUAL
CONNECT BY LEVEL <= (TO_DATE('08-JAN-2020') - TO_DATE('01-JAN-2020'))
)
)
),
THE_GOODS AS (
select name, to_char(DATE_TIME, 'YYYY-MM-DD') AS ADAY, count(*) AS HOW_MANY
from TBLACCESSLOGS
where trunc(DATE_TIME, 'DD') between to_date('2020-01-01', 'YYYY-MM-DD')
and to_date('2020-01-05', 'YYYY-MM-DD')
and remarks = 'LATE'
group by name, to_char(DATE_TIME, 'YYYY-MM-DD')
)
,
PERMS AS (
SELECT DISTINCT DAYS.ADAY, THE_GOODS.NAME
FROM DAYS
CROSS JOIN
THE_GOODS
)
SELECT p.NAME, p.ADAY, COALESCE(g.HOW_MANY, 0) AS HOWMANY
FROM PERMS p
LEFT JOIN THE_GOODS g
on p.ADAY = g.ADAY
and p.NAME = g.NAME
ORDER BY p.ADAY, g.NAME
Upvotes: 1