SQL MONTH AVERGE - sql

Here is what I got to get the duration of the two.
select (TO_TIMESTAMP(s.END, 'hh24:mi:ss') - TO_TIMESTAMP(s.START, 'hh24:mi:ss')) from SESSION s;
I am trying to get the average per month. I do have a time dimension that I can refer to using month_name from the table. However, how to I do this? I have tried to use add_months by casting it but got no luck.
Thank you guys.
VARCHAR for all.
DATE START END RESULT OF QUERY AVERAGE PER MONTH
13-FEB-11 16:00:00 18:00:00 +00 02:00:00.000000 ?
02-APR-11 08:30:00 10:30:00 +00 02:00:00.000000
02-APR-11 16:00:00 18:00:00 +00 02:00:00.000000
05-APR-11 08:30:00 10:30:00 +00 02:00:00.000000
05-APR-11 16:00:00 18:00:00 +00 02:00:00.000000

I would suggest turning the scripts to dates instead of timestamps. This gives you a numeric result that represents the interval as days, which, unlike an interval, you can average.
If you want the average session duration per month, you can aggregate like so:
select
trunc(to_date(s.date, 'dd-mon-yy'), 'mm') mnt,
avg(to_date(s.end, 'hh24:mi:ss') - to_date(t.start, 'hh24:mi:ss')) avg_duration
from session s
group by trunc(to_date(s.date, 'dd-mon-yy'), 'mm')
If you want the result as an interval, you can use numtodsinterval() on the results of the computation:
select
trunc(to_date(s.date, 'dd-mon-yy'), 'mm') mnt,
numtodsinterval(
avg(to_date(s.end, 'hh24:mi:ss') - to_date(t.start, 'hh24:mi:ss')),
'day'
) avg_interval
from session s
group by trunc(to_date(s.date, 'dd-mon-yy'), 'mm')

Related

Getting extra days from generrate_series

I have the following command
select generate_series('2019-09-01'::timestamp, least(current_date, '2019-09-18'), interval '1 week')
which returns me back
2019-09-01 00:00:00
2019-09-08 00:00:00
2019-09-15 00:00:00
Is it possible to get last result as well even id doesn't fit specified interval?
So I'd like to get back
2019-09-01 00:00:00
2019-09-08 00:00:00
2019-09-15 00:00:00
2019-09-18 00:00:00
Well you could union with that final date:
select generate_series('2019-09-01'::timestamp, least(current_date, '2019-09-18'), interval '1 week')
union
select '2019-09-18'::date;
Should your generate series happen to also include the final date, the union would remove one of the two duplicates. Otherwise, the union would include this final date.
Apply greatest() in the subquery, and then least() in the main query :
select least(date, '2019-09-18') as "Date Interval"
from
(
select
generate_series('2019-09-01'::timestamp,
greatest(current_date, '2019-09-18'),
interval '1 week') as date ) q
Demo

Filter By date with format 'dd/mm'

I have difficulty in syntax query dbms oracle for filtering by date, but i just want filter by date with format (dd/mm). and my data database record is (dd/mm/yyyy). How query to filter by date mm/dd
tablename.fieldname >= '01/01'
with s as (
select date '2019-01-01' + level * 15 dt from dual connect by level <= 20)
select s.*
from s
where to_number(to_char(dt, 'mmdd')) > 0501;
DT
-------------------
2019-05-16 00:00:00
2019-05-31 00:00:00
2019-06-15 00:00:00
2019-06-30 00:00:00
2019-07-15 00:00:00
2019-07-30 00:00:00
2019-08-14 00:00:00
2019-08-29 00:00:00
2019-09-13 00:00:00
2019-09-28 00:00:00
2019-10-13 00:00:00
2019-10-28 00:00:00
12 rows selected.
Have you tried something like this? Though it's not exactly the format you wanted
SELECT * from yourTableName
WHERE EXTRACT(month from yourDateColumn) >= '1'
AND EXTRACT(day from yourDateColumn) >= '1';
Oracle EXTRACT documentaion
Possible related questions:
Compare only day and month with date field in mysql
SQL Filter Out Specific Month, Day, and Time for Any Year

SQL: I need to format a Select Distinct Statement with a Case as one of the values

So I'm trying to select the distinct operators from a table with a time component that is formatted like this: 'MM/DD/YYYY HH:MI:SS AM.'
The logic is this:
(if C_StartTime >= date(C_StartTime) + 6:00:00 AM
AND C_StartTime < date(C_StartTime) + 5:59:59AM
then C_StartTime,'MM/DD/YYYY'
ELSE (C_StartTime,'MM/DD/YYYY')-1)
AS DateOnly
I can select distinct operators right now but they sign in and out a few times a day so the time is different. It should be noted that "Today" at this company is 3/13/19 6:00:00 AM to 3/14/19 5:59:59 AM.
Below is the final code I tried executing
SELECT
DISTINCT (
(
CASE WHEN C_StartTime >= date(C_StartTime) +.25
AND C_StartTime < date(C_StartTime) +.9999
THEN date(C_StartTime)
ELSE date(C_StartTime) -1
) as DateOnly,
C_operator,
C_operatorname,
C_WorkCentreName
FROM
OPERATORTABLE
WHERE
.....
EDIT>>>>>>
This is what I get.
This is what I need
I'm Looking for the operator number, the operator name, and the date only (with the knowledge that 1/4/2019 5:59:00 AM = 1/3/2019
I think you're probably after something like trunc(c_starttime - 6/24) + 6/24 to get the day to start at 6am instead of midnight:
WITH dts AS (SELECT to_date('13/03/2019 05:59:59', 'dd/mm/yyyy hh24:mi:ss') dt FROM dual UNION ALL
SELECT to_date('13/03/2019 06:00:00', 'dd/mm/yyyy hh24:mi:ss') dt FROM dual UNION ALL
SELECT to_date('13/03/2019 06:00:01', 'dd/mm/yyyy hh24:mi:ss') dt FROM dual UNION ALL
SELECT to_date('14/03/2019 05:59:59', 'dd/mm/yyyy hh24:mi:ss') dt FROM dual UNION ALL
SELECT to_date('14/03/2019 06:00:00', 'dd/mm/yyyy hh24:mi:ss') dt FROM dual)
SELECT dt,
dt - 6/24 adj_dt,
TRUNC(dt - 6/24) trunc_adj_dt,
TRUNC(dt - 6/24) + 6/24 adj_start_of_dt
FROM dts;
DT ADJ_DT TRUNC_ADJ_DT ADJ_START_OF_DT
------------------- ------------------- ------------------- -------------------
13/03/2019 05:59:59 12/03/2019 23:59:59 12/03/2019 00:00:00 12/03/2019 06:00:00
13/03/2019 06:00:00 13/03/2019 00:00:00 13/03/2019 00:00:00 13/03/2019 06:00:00
13/03/2019 06:00:01 13/03/2019 00:00:01 13/03/2019 00:00:00 13/03/2019 06:00:00
14/03/2019 05:59:59 13/03/2019 23:59:59 13/03/2019 00:00:00 13/03/2019 06:00:00
14/03/2019 06:00:00 14/03/2019 00:00:00 14/03/2019 00:00:00 14/03/2019 06:00:00
I've selected the adj_dt and trunc_adj_dt columns so that you can see how the adj_start_of_dt column was calculated from the original dt column.
You may not need to output 6am on the start date column, so you can skip that (i.e. it's trunc_adj_dt that is the column you'd be after in that case).

How to extract time from a date column in the where clause in ORACLE?

I want to select rows with a specific time interval but the date doesn't matter. So I need a function to return just the time part. I tried using:
to_char(mydate, 'HH12:MI:SS') between '00:00:00' and '08:00:00'
but this doesn't seem to work. Any ideas?
With some sample data you can see that using HH12 doens't necessarly produce the strings you are expecting:
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
-- CTE just for dummy data
with mytable (mydate) as (
select cast(timestamp '2018-08-01 00:00:00' as date) from dual
union all select cast(timestamp '2018-08-02 07:59:59' as date) from dual
union all select cast(timestamp '2018-08-03 08:00:00' as date) from dual
union all select cast(timestamp '2018-08-04 08:00:01' as date) from dual
union all select cast(timestamp '2018-08-05 19:59:59' as date) from dual
union all select cast(timestamp '2018-08-06 20:00:00' as date) from dual
union all select cast(timestamp '2018-08-07 20:00:01' as date) from dual
)
-- actual query
select mydate,
to_char(mydate, 'HH24:MI:SS') as time_24,
to_char(mydate, 'HH12:MI:SS') as time_12
from mytable;
MYDATE TIME_24 TIME_12
------------------- -------- --------
2018-08-01 00:00:00 00:00:00 12:00:00
2018-08-02 07:59:59 07:59:59 07:59:59
2018-08-03 08:00:00 08:00:00 08:00:00
2018-08-04 08:00:01 08:00:01 08:00:01
2018-08-05 19:59:59 19:59:59 07:59:59
2018-08-06 20:00:00 20:00:00 08:00:00
2018-08-07 20:00:01 20:00:01 08:00:01
So when you try to filter using that HH12-based string it includes records you don't expect to see, between 8am and 8pm; and also excludes midnight (as that is '12:00:00' not '00:00:00'):
select mydate
from mytable
where to_char(mydate, 'HH12:MI:SS') between '00:00:00' and '08:00:00';
MYDATE
-------------------
2018-08-02 07:59:59
2018-08-03 08:00:00
2018-08-05 19:59:59
2018-08-06 20:00:00
If you use HH24 instead then you get
select mydate
from mytable
where to_char(mydate, 'HH24:MI:SS') between '00:00:00' and '08:00:00';
MYDATE
-------------------
2018-08-01 00:00:00
2018-08-02 07:59:59
2018-08-03 08:00:00
Also, notice that between is inclusive, so it picks up records at exactly 08:00:00. That may not be what you want - if you're splitting the day into three 8-hour periods, you don't data for that second to be included multiple times; so you can use a more explicit range instead:
select mydate
from mytable
where to_char(mydate, 'HH24:MI:SS') >= '00:00:00'
and to_char(mydate, 'HH24:MI:SS') < '08:00:00';
MYDATE
-------------------
2018-08-01 00:00:00
2018-08-02 07:59:59
then your second shift is:
where to_char(mydate, 'HH24:MI:SS') >= '08:00:00'
and to_char(mydate, 'HH24:MI:SS') < '16:00:00';
and your third shift is:
where to_char(mydate, 'HH24:MI:SS') >= '16:00:00';
or if you prefer, for consistency:
where to_char(mydate, 'HH24:MI:SS') >= '16:00:00'
and to_char(mydate, 'HH24:MI:SS') < '24:00:00';
You can't ever get the hour reported as 24 but as it's a string comparison that doesn't matter here, though it is slightly jarring.
TO_CHAR(mydate, 'HH24:MI:SS')
WHERE mydate BETWEEN '00:00:00' AND '08:00:00';

Previous Weekdays

I have a requirement in which i have to find start and end date.
Start date is First sat of the previous month of created date and end date is previous friday of created date.
Eg Below .. I am passing created date and need to derive start and end date like this below.
CREATED_DT Start_date end_date
04/08/2015 15:36 04/07/2015 00:00 31/07/2015 23:59
07/07/2015 15:32 06/06/2015 00:00 03/07/2015 23:59
You should not depend on the locale-specific NLS settings.
You could use following functions:
NEXT_DAY
ADD_MONTHS
TRUNC
For example,
SQL> alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';
SQL> WITH t(created_dt) AS(
2 SELECT to_date('04/08/2015 15:36','DD/MM/YYYY HH24:MI') FROM DUAL UNION ALL
3 SELECT to_date('07/07/2015 15:32','DD/MM/YYYY HH24:MI') FROM DUAL
4 )
5 SELECT CREATED_DT,
6 NEXT_DAY(TRUNC(add_months(created_dt, -1),'MM') -1,TO_CHAR(to_date('6','J'),'Day')) -1 start_date,
7 NEXT_DAY(TRUNC(created_dt, 'MM') -1, TO_CHAR(to_date('5','J'),'Day')) -1 + 0.99999 AS end_date
8 FROM t;
CREATED_DT START_DATE END_DATE
------------------- ------------------- -------------------
04/08/2015 15:36:00 04/07/2015 00:00:00 31/07/2015 23:59:59
07/07/2015 15:32:00 06/06/2015 00:00:00 03/07/2015 23:59:59
SQL>
To get the time portion as 23:59:59, you could either add 0.99999 or subtract INTERVAL '1' SECOND. For example,
SQL> alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';
Session altered.
SQL> WITH t(created_dt) AS(
2 SELECT to_date('04/08/2015 15:36','DD/MM/YYYY HH24:MI') FROM DUAL UNION ALL
3 SELECT to_date('07/07/2015 15:32','DD/MM/YYYY HH24:MI') FROM DUAL
4 )
5 SELECT CREATED_DT,
6 NEXT_DAY(TRUNC(add_months(created_dt, -1),'MM') -1,TO_CHAR(to_date('6','J'),'Day')) -1 start_date,
7 NEXT_DAY(TRUNC(created_dt, 'MM') -1, TO_CHAR(to_date('5','J'),'Day')) - (INTERVAL '1' SECOND) AS end_date
8 FROM t;
CREATED_DT START_DATE END_DATE
------------------- ------------------- -------------------
04/08/2015 15:36:00 04/07/2015 00:00:00 31/07/2015 23:59:59
07/07/2015 15:32:00 06/06/2015 00:00:00 03/07/2015 23:59:59
SQL>
You can use some of the Date functions. I'm giving for sysdate. Use according to your requirement.
select NEXT_DAY(trunc((trunc (add_months (sysdate, -1), 'mm')), 'MONTH')-1, 'Saturday') as Start_date,
NEXT_DAY(SYSDATE-8, 'FRIDAY') as End_date
from dual;
Output
START_DATE END_DATE
04-JUL-15 21-AUG-15
Use Next_day function. The Oracle/PLSQL NEXT_DAY function returns the first weekday that is greater than a date.
select TO_DATE('04/08/2015 15:36' ,'DD/MM/YYYY hh24:mi') as created_date,
next_day(ADD_MONTHS(TRUNC(TO_DATE('04/08/2015 15:36','DD/MM/YYYY hh24:mi')+1,'MM'),-1),'SATURDAY')
as start_date,
next_day(trunc(TO_DATE('04/08/2015 15:36','DD/MM/YYYY hh24:mi')-8)+0.99999 ,'FRIDAY')as end_date
FROM DUAL
Instead of adding 0.99999 we can also achieve same thing with 1-(1/(24*60*60)) we are adding one day after that subtracting 1 part from 24*60*60 seconds.
I have achieved by this way
end date: Where created _dt is date value what i am passing..!!
next_day(TRUNC(to_date(created_dt,'DD-MM-YYYY HH24:MI:SS'))-7,'FRIDAY') +
INTERVAL '23:59:59' HOUR TO SECOND AS range_end_dt