Trying to resolve a SQL Query issue - sql

I’ve this 2 below SQL Queries which only differs in date-time criteria, one will return data and other will not… Can someone please help…?
Query which returns data –
SELECT *
FROM CA_CLN_CAPM_TRANSPORT,
CA_ENCOUNTER_REF TRANSPORT_PATIENT_ENCOUNTER,
(SELECT DISTINCT TRANSPORT_PATIENT_ATTRIBUTES.ENCOUNTER_ID,
TRANSPORT_PATIENT_ATTRIBUTES.ATTRIBUTE_NAME
FROM CA_CAPM_ENCOUNTER_ATTR TRANSPORT_PATIENT_ATTRIBUTES,
CA_CLN_CAPM_TRANSPORT
WHERE (CA_CLN_CAPM_TRANSPORT.SCHEDULED_DTTM BETWEEN TRANSPORT_PATIENT_ATTRIBUTES.EFF_BEGIN_DTTM AND NVL(TRANSPORT_PATIENT_ATTRIBUTES.EFF_END_DTTM,SYSDATE)
OR NVL(CA_CLN_CAPM_TRANSPORT.COMPLETE_DTTM,SYSDATE) BETWEEN TRANSPORT_PATIENT_ATTRIBUTES.EFF_BEGIN_DTTM AND NVL(TRANSPORT_PATIENT_ATTRIBUTES.EFF_END_DTTM,SYSDATE)
OR TRANSPORT_PATIENT_ATTRIBUTES.EFF_BEGIN_DTTM BETWEEN CA_CLN_CAPM_TRANSPORT.SCHEDULED_DTTM AND NVL(CA_CLN_CAPM_TRANSPORT.COMPLETE_DTTM,SYSDATE))
AND CAST(CA_CLN_CAPM_TRANSPORT.SCHEDULED_DTTM AS DATE) BETWEEN '30-06-2016 12:00:00' AND **'30-06-2016 23:59:00'**
) PATIENT_ATTRIBUTES
WHERE CA_CLN_CAPM_TRANSPORT.ENCOUNTER_ID = TRANSPORT_PATIENT_ENCOUNTER.ENCOUNTER_ID
AND TRANSPORT_PATIENT_ENCOUNTER.ENCOUNTER_ID = PATIENT_ATTRIBUTES.ENCOUNTER_ID(+)
AND TRANSPORT_PATIENT_ENCOUNTER.PATIENT_ID <> '0'
AND CAST(CA_CLN_CAPM_TRANSPORT.SCHEDULED_DTTM AS DATE) BETWEEN '30-06-2016 12:00:00' AND **'30-06-2016 23:59:00'**;
Query which doesn’t return data -
SELECT *
FROM CA_CLN_CAPM_TRANSPORT,
CA_ENCOUNTER_REF TRANSPORT_PATIENT_ENCOUNTER,
(SELECT DISTINCT TRANSPORT_PATIENT_ATTRIBUTES.ENCOUNTER_ID,
TRANSPORT_PATIENT_ATTRIBUTES.ATTRIBUTE_NAME
FROM CA_CAPM_ENCOUNTER_ATTR TRANSPORT_PATIENT_ATTRIBUTES,
CA_CLN_CAPM_TRANSPORT
WHERE (CA_CLN_CAPM_TRANSPORT.SCHEDULED_DTTM BETWEEN TRANSPORT_PATIENT_ATTRIBUTES.EFF_BEGIN_DTTM AND NVL(TRANSPORT_PATIENT_ATTRIBUTES.EFF_END_DTTM,SYSDATE)
OR NVL(CA_CLN_CAPM_TRANSPORT.COMPLETE_DTTM,SYSDATE) BETWEEN TRANSPORT_PATIENT_ATTRIBUTES.EFF_BEGIN_DTTM AND NVL(TRANSPORT_PATIENT_ATTRIBUTES.EFF_END_DTTM,SYSDATE)
OR TRANSPORT_PATIENT_ATTRIBUTES.EFF_BEGIN_DTTM BETWEEN CA_CLN_CAPM_TRANSPORT.SCHEDULED_DTTM AND NVL(CA_CLN_CAPM_TRANSPORT.COMPLETE_DTTM,SYSDATE))
AND CAST(CA_CLN_CAPM_TRANSPORT.SCHEDULED_DTTM AS DATE) BETWEEN '30-06-2016 12:00:00' AND **'01-07-2016 23:59:00'** –Running for longer time frame
) PATIENT_ATTRIBUTES
WHERE CA_CLN_CAPM_TRANSPORT.ENCOUNTER_ID = TRANSPORT_PATIENT_ENCOUNTER.ENCOUNTER_ID
AND TRANSPORT_PATIENT_ENCOUNTER.ENCOUNTER_ID = PATIENT_ATTRIBUTES.ENCOUNTER_ID(+)
AND TRANSPORT_PATIENT_ENCOUNTER.PATIENT_ID <> '0'
AND CAST(CA_CLN_CAPM_TRANSPORT.SCHEDULED_DTTM AS DATE) BETWEEN '30-06-2016 12:00:00' AND **'01-07-2016 23:59:00'**;

The problem is your use of strings to represent the date-time values. If we run DUMP() on your strings we get this:
SQL> select dump('30-06-2016 12:00:00') as dt
2 from dual
3 /
DT
-----------------------------------------------------------------------
Typ=96 Len=19: 51,48,45,48,54,45,50,48,49,54,32,49,50,58,48,48,58,48,48
SQL>
Typ=96 means it's a CHAR value (a date would be Typ=12). So Oracle will apply character semantics to the operation. In effect this ...
x BETWEEN '30-06-2016 12:00:00' AND '01-07-2016 23:59:00'
... evaluates to ...
'30' >= '30' AND '30' <= '01'
... which is clearly nonsense.
What you need to do is use explicit casts with a format mask:
BETWEEN to_date('30-06-2016 12:00:00', 'DD-MM-YYYY HH24:MI:SS')
AND to_date('01-07-2016 23:59:00', 'DD-MM-YYYY HH24:MI:SS')

Related

Select a date within a year in SQL Oracle

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.

SQL query to sum timestamp diff with null handling

I have a (Oracle)DB table with 2 columns t1 and t2 both with datatype timestamp. column t2 is nullable. I need a SQL query to give me something like the below pseudocode.
sum ((t2 if t2 !=null else sys.currentTimestamp) - t1)
There are two issues here. Firstly, how to substitute a default value for a null. That's easy, we have nvl and coalesce. For example:
with demo (t1, t2) as
( select timestamp '2020-01-01 00:00:00'
, timestamp '2020-01-01 01:02:03'
from dual
union all
select timestamp '2020-01-01 00:00:00', null from dual )
select t1
, t2
, nvl(t2, current_timestamp)
from demo;
T1 T2 NVL(T2,CURRENT_TIMESTAMP)
---------------------- ---------------------- -----------------------------
2020-01-01 00:00:00.00 2020-01-01 01:02:03.00 2020-01-01 01:02:03.000000000
2020-01-01 00:00:00.00 2020-08-28 11:25:22.989000000
The harder part is how to sum t2 - nvl(t2,current_timestamp). The difference between two timestamps is an interval day to second, and although you can do arithmetic with intervals (add, subtract, multiply etc), you can't currently sum them. (You can add your vote to this suggestion on the Oracle Database Ideas forum to get the functionality added.)
In the meantime, you can either write your own using the Oracle Data Cartridge Interface, or use a workaround such as this one from Stew Stryker:
with demo (t1, t2) as
( select timestamp '2020-01-01 00:00:00'
, timestamp '2020-01-01 01:02:03'
from dual
union all
select timestamp '2020-01-01 00:00:00', null from dual )
select numtodsinterval(
sum(
((sysdate + (nvl(t2,systimestamp) -t1)) - sysdate) * 86400
+ extract(second from (nvl(t2,systimestamp) -t1))
- trunc(extract(second from (nvl(t2,systimestamp) -t1)))
)
, 'second'
) as duration
from demo;
DURATION
--------------------------------------------------------------------------------
+000000240 12:37:23.646000000

Need to find the difference between two timestamp in hours using oracle sql

SELECT MAX(
CASE
WHEN CLKTRANTYPE_ID = 1
THEN MIN((TO_CHAR (CLKTRANPRO_TIME,'YYYY.MM.DD HH24:MI:SS')))
END) AS MIN_TIME ,
MAX(
CASE
WHEN CLKTRANTYPE_ID = 2
THEN MAX((TO_CHAR(CLKTRANPRO_PROC_DT,'YYYY.MM.DD HH24:MI:SS')) )
END) AS MAX_TIME
FROM CLOCK_TRAN_PROCESSED
WHERE WRKS_ID =1652201
GROUP BY WRKS_ID,CLKTRANTYPE_ID;
Above is my Query and i need to find the difference between MAX_TIME and MIN_TIME in hours format . I tried using extract and (-) but nothing working for me. Please help me to find the difference in Hours format.
Difference in hours
select 24 * (to_date('2017-07-07 22:00', 'YYYY-MM-DD hh24:mi')
- to_date('2017-07-07 19:30', 'YYYY-MM-DD hh24:mi')) diff_in_hours
from dual;
Result for above query should be 2.5 hrs
Simple way to get difference
select Date1 - Date2 from your_Table;
Why would you convert the values to strings to get the difference?
select (extract(day from max(CLKTRANPRO_PROC_DT) - min(CLKTRANPRO_TIME)) * 24 +
extract(hour from max(CLKTRANPRO_PROC_DT) - min(CLKTRANPRO_TIME))
) as diff_hours

Oracle query time on date fields

I have a column of type DATE stored data are contains date and time . I can see value when i do
select CAST(MSG_DT AS TIMESTAMP) from table;
this is the output
17-MAR-08 15:38:59,000000000
I have to select the row using
Only date
select CAST(MSG_DT AS TIMESTAMP) from
MWRB_RECEIVE where
MSG_DT >= TO_DATE( '2000-02-03' ,'YYYY-MM-DD')
and
MSG_DT <= TO_DATE( '2010-02-03' ,'YYYY-MM-DD')
Only time (eg: every message between 12:00:11 and 23:02:55)
In DB2 i can do
SELECT *
FROM TABLE
WHERE DATE(INS_TMS) = '2014-02-18'
SELECT *
FROM TABLE
WHERE TIME(INS_TMS) > '09.55.00'
In ORACLE I can't see the equivalent.
Try this:
SELECT *
FROM your_table
WHERE TO_CHAR (start_date, 'yyyy-mm-dd') = '2014-10-06'
AND TO_CHAR (start_date, 'hh24:mi:ss') > '10:00:00'
Why are you casting the column value to a TIMESTAMP when the column in the database is a DATE type? The fractional part of the seconds will always be 0, as DATE only has resolution to the seconds value. You need to add the hours,minutes, and seconds format specifier to the query:
select MSG_DT from
MWRB_RECEIVE
where MSG_DT between TO_DATE( '2000-02-03 12:00:11' ,'YYYY-MM-DD HH24:MI:SS') AND
TO_DATE( '2010-02-03 23:02:55' ,'YYYY-MM-DD HH24:MI:SS')
There is no need to split date and hour, you can have it in a single where clause
where field > to_date('20121212 12:12:12, 'YYYYMMDD HH24:MI:SS')
Check for your reference oracle to_date() as it seems the only thing you need

Oracle Set operator query

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.