Case and Where condition - sql

Following is my sql code. I want all the ids with description that have create time or update time between 25-Aug to 31-Aug.
Currently, if an id has create time between 25-Aug to 31-Aug, though the update time is in Sep, the sql is returning the record for the update time.
Ideally it should only return the records that have create or update times between 25-Aug to 31-Aug. Why is my case ignoring the condition for update time?
select t1.id, t1.desc,
Case
WHEN t1.create_time IS NOT NULL
THEN t1.create_time
WHEN t2.update_time IS NOT NULL
THEN t2.update_time
END AS "TimeStamp"
from t1, t2
where t1.id=t2.id(+)
AND ( t1.create_time BETWEEN TO_DATE ('25-AUG-2016 00:00:00',
'dd-mon-yyyy HH24:Mi:SS')
AND TO_DATE ('31-AUG-2016 23:59:59',
'dd-mon-yyyy HH24:Mi:SS')
OR ( t2.update_time
BETWEEN TO_DATE ('25-AUG-2016 00:00:00',
'dd-mon-yyyy HH24:Mi:SS')
AND TO_DATE ('31-AUG-2016 23:59:59',
'dd-mon-yyyy HH24:Mi:SS')
)
)

In your query conditions for create_time and update_time combined by OR. When we combine two condition by OR, if one of condition is TRUE then result also will be TRUE. As result, in your query if create_time falls within the range, then not metter update_time falls within the range or not.
You can use subqueries to filter tables before you join them
select t1_1.id, t1_1.desc,
CASE
WHEN t1_1.create_time IS NOT NULL
THEN t1_1.create_time
WHEN t2_1.update_time IS NOT NULL
THEN t2_1.update_time
END AS "TimeStamp"
from (select * from t1
where t1.create_time BETWEEN TO_DATE ('25-AUG-2016 00:00:00',
'dd-mon-yyyy HH24:Mi:SS')
AND TO_DATE ('31-AUG-2016 23:59:59',
'dd-mon-yyyy HH24:Mi:SS')) t1_1,
(select * from t2
where t2.update_time BETWEEN TO_DATE ('25-AUG-2016 00:00:00',
'dd-mon-yyyy HH24:Mi:SS')
AND TO_DATE ('31-AUG-2016 23:59:59',
'dd-mon-yyyy HH24:Mi:SS')) t2_1
where t1_1.id_=t2_1.id_(+)

Try this:
SELECT t1.id, t1.desc,
t1.create_time 'TimeStamp'
from t1
where
trunc(t1.create_time) BETWEEN TO_DATE ('25-AUG-2016','DD-MON-YYYY')
AND TO_DATE ('31-AUG-2016','DD-MON-YYYY')
union all
SELECT t1.id, t1.desc,
t1.update_time 'TimeStamp'
from t1
where
( trunc(t1.update_time)
BETWEEN TO_DATE ('25-AUG-2016','DD-MON-YYYY')
AND TO_DATE ('31-AUG-2016','DD-MON-YYYY')
)

Related

Group by singles chute

How can I create an overview without duplicates in column "CHUTE"?
Eg in below result: AX002 = 129
select
COUNT(PPL_SDCC),
substr (PPL_DISCHARGEID,6,5) as CHUTE
from T1LOG.PPL_PIECELOG
where
PPL_DISCHARGEID like 'PS%X%'
and substr (PPL_SDCC,11,1)='1'
and PPL_DISCHARGETIME between TO_DATE ('01/08/2021 10:00:00' , 'DD/MM/YYYY hh24:mi:ss') and TO_DATE ('02/08/2021 09:00:00' , 'DD/MM/YYYY hh24:mi:ss')
group by PPL_DISCHARGEID
order by CHUTE
RESULT:
Rahther than grouping only column PPL_DISCHARGEID, You should actually include the exact calculation in group by clause. Please update your group by clause in your query to -
SELECT COUNT(PPL_SDCC),
SUBSTR(PPL_DISCHARGEID,6,5) as CHUTE
FROM T1LOG.PPL_PIECELOG
WHERE PPL_DISCHARGEID like 'PS%X%'
AND SUBSTR(PPL_SDCC,11,1)='1'
AND PPL_DISCHARGETIME BETWEEN TO_DATE('01/08/2021 10:00:00', 'DD/MM/YYYY hh24:mi:ss') and TO_DATE('02/08/2021 09:00:00', 'DD/MM/YYYY hh24:mi:ss')
GROUP BY SUBSTR(PPL_DISCHARGEID,6,5)
ORDER BY CHUTE;

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.

TO_CHAR only considering dates while comparing two time stamps?

In the below query condition is failing but logically it should pass. Is something wrong with to_char??
SELECT data
FROM table1
WHERE
TO_CHAR(TO_DATE(value1, 'DD/MM/RRRR HH24:MI:SS'), 'DD/MM/RRRR HH24:MI:SS') <=
TO_CHAR( SYSDATE, 'DD/MM/RRRR HH24:MI:SS')
AND TO_CHAR(TO_DATE(value2, 'DD/MM/RRRR HH24:MI:SS'), 'DD/MM/RRRR HH24:MI:SS') >=
TO_CHAR( SYSDATE, 'DD/MM/RRRR HH24:MI:SS');
value1='02/07/2014 12:30:10'
value2='06/08/2015 09:57:33'
in both the conditions it is only checking the dates i.e.,02<=07 (7th is todays date).First condition is getting satisfied regardless of month and year.if i change value1 to '15/08/2014 12:30:10' it is failing. Same with second condition.
Why are you comparing dates as strings? This also begs the question of why you would store dates as strings in the first place. You should store date/times using the built-in types.
Try this instead:
SELECT data
FROM table1
WHERE TO_DATE(value1, 'DD/MM/RRRR HH24:MI:SS') <= sysdate AND
TO_DATE(value2, 'DD/MM/RRRR HH24:MI:SS') >= sysdate;
Your problem is presumably that you are comparing strings, rather than dates. And the format you are using DD/MM/YYYY doesn't do comparisons the same way. This is, in fact, why you should just use the ISO format of YYYY-MM-DD whenever you are storing date/time values in strings (which I don't recommend in most cases anyway).
If your values are already stored in proper types, then you can just do:
SELECT data
FROM table1
WHERE value1 <= sysdate AND
value2 >= sysdate;
If these are timestamps with time zone, then you can use SYSTIMESTAMP instead of SYSDATE.
Finally after lot of googling i got the solution. Below query is working for me :) :)
SELECT MESSAGE
FROM TABLE1
WHERE TO_TIMESTAMP(value1, 'DD/MM/RRRR HH24:MI:SS') <= CAST(SYSDATE AS TIMESTAMP)
AND TO_TIMESTAMP(value2, 'DD/MM/RRRR HH24:MI:SS') >= CAST(SYSDATE AS TIMESTAMP);
value1='02/07/2014 12:30:10'
value2='06/08/2015 09:57:33'
You have to use TO_TIMESTAMP instead of TO_DATE:
SELECT data
FROM table1
WHERE
TO_CHAR(TO_TIMESTAMP(value1, 'DD/MM/RRRR HH24:MI:SS'), 'DD/MM/RRRR HH24:MI:SS') <=
TO_CHAR( SYSDATE, 'DD/MM/RRRR HH24:MI:SS')
AND TO_CHAR(TO_TIMESTAMP(value2, 'DD/MM/RRRR HH24:MI:SS'), 'DD/MM/RRRR HH24:MI:SS') >=
TO_CHAR( SYSDATE, 'DD/MM/RRRR HH24:MI:SS');

How do I query for something that starts with certain characters?

Here is my code:
SELECT SRV_NAME, TOT_CPU, TOT_MEM, SNAP_DATE
FROM capacity.SRV_CAPACITY_SEV
WHERE SRV_NAME in ('absshs1p", "AA03server', 'AA02server', 'BA01server', 'BA03server', 'BC03server') AND SNAP_DATE BETWEEN to_date('10-jun-2012 00:00:00', 'dd-mon-yyyy hh24:mi:ss') AND to_date('12-jun-2012 00:00:00', 'dd-mon-yyyy hh24:mi:ss')
ORDER BY SRV_NAME desc, SNAP_DATE desc;
How would I query for servers that begin with certain characters? For example, how could I serach for servers that only begin with 'AA'?
I am using Oracle SQL btw.
You can do this
WHERE SRV_NAME LIKE 'AA%'

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.