I want to get all rows from my table, the table have one column with the following date type '14/07/2017 05:01:35 p.m.' between specific hours. Like between '00:01:00 am' and '01:00:00 am'.
I'm running Oracle Database 11g Release 2
select ID, CREATION_TIME
from my_table
where ID = 4 and
CREATION_TIME between to_date('29/04/2017 12:01:00', 'DD/MM/YYYY HH:MI:SS[AM]') and to_date('29/04/2019 01:00:00', 'DD/MM/YYYY HH:MI:SS[AM]')
order by creation_time asc;
I want to select hours instead of dates.
If you mean (from your last comment) that you want to get all records that are between the dates of Jan 1st 2019 and Apr 4th 2019, but only if the time portion of the recod is between 12:01AM and 1:00AM, then you could try this:
select ID, CREATION_TIME
from my_table
where ID = 4
and CREATION_TIME between to_date('01/01/2017', 'DD/MM/YYYY')
and to_date('04/04/2019', 'DD/MM/YYYY')
and CREATION_TIME BETWEEN TO_DATE(TO_CHAR(CREATION_TIME, 'MM/DD/YYYY') || ' 00:01:00', 'MM/DD/YYYY HH24:MI:SS')
AND
TO_DATE(TO_CHAR(CREATION_TIME, 'MM/DD/YYYY') || ' 01:00:00', 'MM/DD/YYYY HH24:MI:SS')
order by creation_time asc;
Related
I have a sales table with created datetime, my business hours are from 9 AM to 2 AM in the night on the following day. I am trying to convert the dates into my business date.
01/08/22 09:39:12.000000000 AM +04:00
Lets say I have a sale at 1 AM, this sale has to be considered in the previous day.
Any function that can help me solve this issue would be appreciated
It might be a bit of an overkill, but you could just use EXTRACT:
WITH dat AS
(
SELECT to_date('01/08/22 09:39:12','DD/MM/YY HH24:MI:SS') AS t_stmp FROM dual UNION ALL
SELECT to_date('02/08/22 01:03:15','DD/MM/YY HH24:MI:SS') FROM dual UNION ALL
SELECT to_date('02/08/22 08:27:33','DD/MM/YY HH24:MI:SS') FROM dual UNION ALL
SELECT to_date('02/08/22 14:11:51','DD/MM/YY HH24:MI:SS') FROM dual UNION ALL
SELECT to_date('02/08/22 02:01:15','DD/MM/YY HH24:MI:SS') FROM dual
)
SELECT CASE WHEN EXTRACT(HOUR FROM CAST(t_stmp AS TIMESTAMP)) BETWEEN 2 AND 8 THEN -1
ELSE 0
END + TRUNC(t_stmp,'DD') AS business_date
FROM dat;
business_date
01.08.2022
02.08.2022
01.08.2022
02.08.2022
01.08.2022
It looks like you just need to make a 2 hour shift to get your sales in the right date. You can add or substract hours from DATE/DATETIME/TIMESTAMP data type. If your column is TIMESTAMP then it would be like this:
-- when selecting data for date of sales
SELECT TRUNC(your_column_name - INTERVAL '2' HOUR, 'dd') "SALE_DATE"
-- And/Or
WHERE TRUNC(your_column_name - INTERVAL '2' HOUR, 'dd') = :DATE_OF_SALES
-- TRUNC function always returns DATE datatype
--
-- The opposite conversion would be
CAST(your_datetime_column + INTERVAL '2' HOUR as TIMESTAMP) ...
Here is the small sample with result:
SELECT
to_char(SYSDATE, 'dd.mm.yyyy hh24:mi:ss') "DATETIME",
to_char(SYSDATE - INTERVAL '2' HOUR, 'dd.mm.yyyy hh24:mi:ss') "DATETIME_MINUS_2H",
to_char(SYSDATE + INTERVAL '2' HOUR, 'dd.mm.yyyy hh24:mi:ss') "DATETIME_PLUS_2H",
to_char(SYSDATE - INTERVAL '10' HOUR, 'dd.mm.yyyy hh24:mi:ss') "DATETIME_MINUS_10H"
FROM
DUAL
--
-- R e s u l t
--
-- DATETIME DATETIME_MINUS_2H DATETIME_PLUS_2H DATETIME_MINUS_10H
-- ------------------- ------------------- ------------------- -------------------
-- 07.08.2022 09:58:38 07.08.2022 07:58:38 07.08.2022 11:58:38 06.08.2022 23:58:38
The last column now has the date from day before.
Given:
INSERT INTO EP_ACCESS (PROFILE_ID, EPISODE_ID, START_TIMESTAMP, DISCONNECT_TIMESTAMP)
VALUES ('1', '1', TO_DATE('2020-01-01 00:00:01','yyyy/mm/dd hh24:mi:ss'), TO_DATE('2020-01-01 00:00:02','yyyy/mm/dd hh24:mi:ss'));
How can I select those who start_timestamp is in 2020?
You would use:
where start_timestamp >= date '2020-01-01' and
start_timestamp < date '2021-01-01'
Of course, you can use a timestamp literal if you prefer typing longer strings.
There are several options.
1 - Use BETWEEN
SELECT *
FROM EP_ACCESS
WHERE START_TIMESTAMP BETWEEN TO_DATE('2020-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND TO_DATE('2020-12-31 23:59:59', 'YYYY-MM-DD HH24:MI:SS')
or
SELECT *
FROM EP_ACCESS
WHERE START_TIMESTAMP BETWEEN DATE '2020-01-01'
AND DATE '2021-01-01' - INTERVAL '1' SECOND
2 - Use EXTRACT
SELECT *
FROM EP_ACCESS
WHERE EXTRACT(YEAR FROM START_TIMESTAMP) = 2020
3 - Use TRUNC
SELECT *
FROM EP_ACCESS
WHERE TRUNC(START_TIMESTAMP, 'YYYY') = DATE '2020-01-01'
Of these options, BETWEEN will probably provide the best performance as the other two require executing a function against the START_TIMESTAMP field in every row in the table.
I am working on this DB that contains informations on shop orders in a plant. I am using this query that retrieves order data, using the closing date as condition. It extracts order that are closed in a time range of two weeks.
select order.id, order.end_date, material.id, material.description
from plant.order inner join plant.material
on order.material = material.id
where order.end_date <= to_date('26/10/2018 06:00:00', 'DD/MM/YYYY HH24:MI:SS')
where order.end_date <= to_date('12/10/2018 06:00:00', 'DD/MM/YYYY HH24:MI:SS')
Since the workday is divided in shifts (for example, the workday 26th October starts from the 26/10 6:00 and ends in 27/10 6:00 to cover the 24 hours), I need to manage this thing.
Is it possible to use a condition that checks if the hour is < 6, and if the condition is true, it writes the correct value in another column?
Or is there a better way to manage it?
order.id order.end_date material.id material.description
-------- -------------- ----------- --------------------
1 26/10/2018 05:00 1 Lorem Ipsum
2 26/10/2018 07:00 2 Lorem Ipsum
order.workday (new column)
-------------
25/10/2018
26/10/2018
In this case the order id 1 should result of date 25/10/2018, while order id 2 should result of date 26/10/2018.
I hope that I have been clear.
Thanks
You could simply use TRUNC(order.end_date - 6/24)
WITH t AS (
SELECT TO_DATE('26/10/2018 05:00' , 'dd/mm/yyyy hh24:mi') AS end_date FROM dual
UNION ALL SELECT TO_DATE('26/10/2018 07:00' , 'dd/mm/yyyy hh24:mi') AS end_date FROM dual)
SELECT end_date, TRUNC(end_date - 6/24)
from t;
+----------------------------------------+
|END_DATE |TRUNC(END_DATE-6/24)|
+----------------------------------------+
|26.10.2018 05:00:00|25.10.2018 |
|26.10.2018 07:00:00|26.10.2018 |
+----------------------------------------+
Try below using CASE WHEN
select
order.id,
order.end_date,
material.id,
material.description,
case when TO_CHAR (order.end_date, 'HH24:MI:SS')<'06:00:00' then order.end_date- interval '1' day else order.end_date end as workday
from plant.order inner join plant.material,
on order.material = material.id
where order.end_date <= to_date('26/10/2018 06:00:00', 'DD/MM/YYYY HH24:MI:SS')
where order.end_date <= to_date('12/10/2018 06:00:00', 'DD/MM/YYYY HH24:MI:SS')
Let's consider I am having following data in my table:
User id date time
User1. 28-JUL-16 06:14:56
User1. 28-JUL-16 04:12:12
User2. 28-JUL -16 05:10:45
User3. 30-JUL-16 03:10:12
I want to find the count of users on date wise.
Please some help on this!
You can ignore the time portion of a date using the trunc() function, which defaults to converting the time part to midnight. You can then group by that.
with your_table (user_id, date_time) as (
select 'User1.', to_date('28-JUL-16 06:14:56', 'DD-MON-RR HH24:MI:SS') from dual
union all select 'User1.', to_date('28-JUL-16 04:12:12', 'DD-MON-RR HH24:MI:SS') from dual
union all select 'User2.', to_date('28-JUL-16 05:10:45', 'DD-MON-RR HH24:MI:SS') from dual
union all select 'User3.', to_date('30-JUL-16 03:10:12', 'DD-MON-RR HH24:MI:SS') from dual
)
select to_char(trunc(date_time), 'DD-MON-RR') as date_only, count(distinct user_id)
from your_table
group by trunc(date_time);
DATE_ONLY COUNT(DISTINCTUSER_ID)
------------------ ---------------------------------------
28-JUL-16 2
30-JUL-16 1
I've included distinct as it isn't clear if you want to count a user more than once n the same day; if you do then just remove that.
select to_char(trunc(date_time), 'DD-MON-RR') as date_only, count(user_id)
from your_table
group by trunc(date_time);
DATE_ONLY COUNT(USER_ID)
------------------ ---------------------------------------
28-JUL-16 3
30-JUL-16 1
Have a SQL query on Oracle 11g which returns the count of whether a record having certain ID and status exists within +/- 15 minutes range in a table.
Now I wish to ignore the current date by adding a condition like AND TIMESTAMP < trunc(sysdate).
However, for cases where the record exists in todays date I wish to ignore the date comparison check in the query '2010-07-20 19:15:11' >= TO_CHAR(TIMESTAMP - (1/1440*15), 'YYYY-MM-DD HH24:MI:SS')
AND '2010-07-20 19:15:11' <= (TO_CHAR(TIMESTAMP + (1/1440*15), 'YYYY-MM-DD HH24:MI:SS'))
SELECT count(1) AS COUNT
FROM MASTER_ONE
WHERE ID='123' AND STATUS= 'ACTIVE'
AND '2010-07-20 19:15:11' >= TO_CHAR(TIMESTAMP - (1/1440*15), 'YYYY-MM-DD HH24:MI:SS')
AND '2010-07-20 19:15:11' <= (TO_CHAR(TIMESTAMP + (1/1440*15), 'YYYY-MM-DD HH24:MI:SS'))
UNION ALL
SELECT count(1) AS COUNT
FROM MASTER_TWO
WHERE ID='321' AND STATUS= 'ACTIVE'
AND '2010-07-20 19:15:11' >= TO_CHAR(TIMESTAMP - (1/1440*15), 'YYYY-MM-DD HH24:MI:SS')
AND '2010-07-20 19:15:11' <= (TO_CHAR(TIMESTAMP + (1/1440*15), 'YYYY-MM-DD HH24:MI:SS'))
How do I do this?
The first problem with your query is that you're doing a string comparison on the date. Use to_date instead of to_char and let Oracle help you out.
SELECT
to_date('2010-07-20 19:15:11', 'YYYY-MM-DD HH24:MI:SS') AS orig_date
, to_date('2010-07-20 19:15:11', 'YYYY-MM-DD HH24:MI:SS') - 1 / 24 / 4 AS fifteen_min_prior
, to_date('2010-07-20 19:15:11', 'YYYY-MM-DD HH24:MI:SS') + 1 / 24 / 4 AS fifteen_min_after
FROM dual;
Output:
ORIG_DATE FIFTEEN_MIN_PRIOR FIFTEEN_MIN_AFTER
------------------------- ------------------------- -------------------------
20-JUL-10 07:15:11 PM 20-JUL-10 07:00:11 PM 20-JUL-10 07:30:11 PM
Then use can use those dates in a BETWEEN condition in the predicate. See Oracle date "Between" Query.
I'm not quite clear what you mean by "However, for cases where the record exists in todays date I wish to ignore the date comparison check in the query." You'd just written that you want to exclude values from the current day. Either you're excluding today's records or you're not.
Ok, you can try something like this, if I understood you correctly:
SELECT count(1) AS COUNT
FROM MASTER_ONE
WHERE ID='123' AND STATUS= 'ACTIVE'
AND (timestamp > trunc(sysdate)
OR (timestamp < trunc(sysdate)
AND timestamp BETWEEN to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') - (1/1440*15)
AND to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') + (1/1440*15)))
UNION ALL
SELECT count(1) AS COUNT
FROM MASTER_TWO
WHERE ID='321' AND STATUS= 'ACTIVE'
AND (timestamp > trunc(sysdate)
OR (timestamp < trunc(sysdate)
AND timestamp BETWEEN to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') - (1/1440*15)
AND to_date(:yourInputDate,'DD/MM/YYYY HH24:MI:SS') + (1/1440*15)))
In this Select, you only apply the 15 minutes condition if your timestamp column has a date prior to sysdate.