Oracle SQL join subquery dblink - sql

Subquery join return error, could not found subquery table. Appreciate any helps!
I have two tables. One is normal one. ops_owner.track_mail_item.
Another one is dblink (not sure how that works, but I run following it works
SELECT TRUNC(event_date,'HH24'),
tmi_uid
FROM TRACK_OWNER.TRACKING_DETAIL#dblink_track
WHERE event_id ='158'
AND event_date BETWEEN to_date('04/01/2017 12:00:01 AM', 'MM/DD/YYYY HH12:MI:SS AM') AND to_date('04/30/2017 11:59:59 PM', 'MM/DD/YYYY HH12:MI:SS PM')
since the dblink table have multiple column as key (tmi_uid and event_id). I want to run subquery to make tmi_uid as key so I can use that later. However, when I run following the error is
ORA-00904: "M"."EVENT_DATE": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action: Error at Line: 21 Column: 6"
SELECT i.originfacilitycode,
i.zip5,
TRUNC(i.receivedate,'HH24'),
TRUNC(m.event_date,'HH24'),
COUNT(i.tmi_uid)
FROM ops_owner.track_mail_item i
inner join (SELECT TRUNC(event_date,'HH24'),
tmi_uid
FROM TRACK_OWNER.TRACKING_DETAIL#dblink_track
WHERE event_id ='158'
AND event_date BETWEEN to_date('04/01/2017 12:00:01 AM', 'MM/DD/YYYY HH12:MI:SS AM') AND to_date('04/30/2017 11:59:59 PM', 'MM/DD/YYYY HH12:MI:SS PM')
) m
ON i.tmi_uid = m.tmi_uid
WHERE I.PRODUCT_ID IN (81, 82, 83, 36)
AND I.RECEIVEDATE BETWEEN to_date('04/01/2017 00:00:01', 'MM/DD/YYYY HH24:MI:SS') AND to_date('04/30/2017 23:59:59', 'MM/DD/YYYY HH24:MI:SS')
AND i.lasteventcountry = 'US'
AND i.zip3 NOT IN ('006', '007', '008', '009', '090', '091', '092', '093', '094', '095', '096', '097', '098', '340', '962', '963', '964', '965', '966', '967', '968', '969', '995', '996', '997', '998', '999')
GROUP BY i.originfacilitycode,
i.zip5,
TRUNC(i.receivedate,'HH24'),
TRUNC(m.event_date,'HH24');
I really appreciate any helps.

This is your subquery for m:
(SELECT TRUNC(event_date,'HH24'), tmi_uid
FROM TRACK_OWNER.TRACKING_DETAIL#dblink_track
WHERE event_id ='158' AND
event_date BETWEEN to_date('04/01/2017 12:00:01 AM', 'MM/DD/YYYY HH12:MI:SS AM') AND to_date('04/30/2017 11:59:59 PM', 'MM/DD/YYYY HH12:MI:SS PM')
) m
It does not name the first column, so you cannot refer to it in an outer query. You can also simplify the date arithmetic, so:
(SELECT TRUNC(event_date,'HH24') as event_date, tmi_uid
FROM TRACK_OWNER.TRACKING_DETAIL#dblink_track
WHERE event_id ='158' AND
event_date >= date '2017-04-01' AND
event_date < date '2017-05-01'
) m

Related

How to compare date with time in oracle

Trying to compare two dates with time.But comparison is not working.
SELECT *
FROM attendance
WHERE TO_DATE (checktime, 'DD/MM/YYYY HH:MI:SS AM') >=
TO_DATE ('01/09/2019 04:30:00 PM', 'DD/MM/YYYY HH:MI:SS AM')
AND TO_DATE (checktime, 'DD/MM/YYYY HH:MI:SS AM') <=
TO_DATE ('30/09/2019 10:00:00 PM', 'DD/MM/YYYY HH:MI:SS AM')
AND userid = '3825'
AND SUBSTR (checktime, -2, 2) = 'PM'
ORDER BY TO_DATE (checktime, 'DD/MM/YYYY HH:MI:SS AM') ASC
I was expecting output equal or grater then 04:30 PM and less then or equal 10:00 PM.But this date comparison is not working.Here is the
Output of Code.I want my result includes date and time between mentioned periods.
Note:CHECKTIME datatype is varchar2.
I think you need data for all the days(01/09/2019 - 30/09/2019) and the time of the day should be between 04:30 PM and 10: PM.
You can achieve this using the following query:
SELECT
*
FROM
ATTENDANCE
WHERE
TRUNC(TO_DATE(CHECKTIME, 'DD/MM/YYYY HH:MI:SS AM'))
BETWEEN TO_DATE('01/09/2019', 'DD/MM/YYYY')
AND TO_DATE('30/09/2019', 'DD/MM/YYYY')
AND ( TO_DATE(CHECKTIME, 'DD/MM/YYYY HH:MI:SS AM') - TRUNC(TO_DATE(CHECKTIME, 'DD/MM/YYYY HH:MI:SS AM')) ) * 1440 -- converting difference into minutes
BETWEEN 990 -- 04:30 PM in minutes (16.5*60)
AND 1320 -- 10:00 PM in minutes (22*60)
AND USERID = '3825'
AND SUBSTR(CHECKTIME, - 2, 2) = 'PM'
ORDER BY
TO_DATE(CHECKTIME, 'DD/MM/YYYY HH:MI:SS AM') ASC;
Cheers!!
You can fix your format by using such a format containing TO_TIMESTAMP conversion
SELECT *
FROM attendance
WHERE checktime
BETWEEN TO_TIMESTAMP('01/09/2019 16:30:00.000000','dd/mm/yyyy hh24:mi:ss.ff')
AND TO_TIMESTAMP('30/09/2019 22:30:00.000000','dd/mm/yyyy hh24:mi:ss.ff')
AND userid = 3825
ORDER BY checktime;
Demo
EDIT : you had better to add a new column with timestamp datatype, and update your new column's data by using TO_TIMESTAMP conversion such as below :
UPDATE attendance
SET checktime2 = TO_TIMESTAMP('3/09/2019 5:38:36 PM','dd/mm/yyyy hh:mi:ss AM')
WHERE id = 3825
AND checktime = '3/09/2019 5:38:36 PM'

Case and Where condition

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')
)

Calculate time difference ignorning non-work hours

I am trying to calculate the difference between 2 datetime values where non-work hours are ignored. Originally it just looked at the difference and calculated it as minutes however It needs to count only hours between 9am and 8pm Monday to Friday and 9am - 1pm Saturday, ignoring all other times. I am on an oracle 10g system.
my code as it currently stands is as follows:
begin
debug.debug('sp_access');
update cl_case b
set time_to_sp_access =
(
select (x.date_created-e.date_created)*1440
from cl_case c, eventlog e, eventlog x
where c.id=e.case_id
and x.case_id=e.case_id
and b.id=e.case_id
and e.id=
( select min(id) from eventlog mini
where mini.case_id=e.case_id
and mini.cl_code in ('AAAA','BBBB','CCCC','DDDD')
)
and x.id=
( select min(id) from eventlog minix
where minix.case_id=e.case_id
and minix.cl_code in ('EEEE','FFF','GGG','HHHH','JJJJ','KKKK','LLLL')
)
)
where id in
( select unique case_id
from eventlog elog
where elog.sptime_needs_setting ='Y'
);
commit;
end sp_access;
How can I get this to count time between specified hours?
thanks
You could use a CASE expression in the WHERE clause. Since there are two datetime values, you need to use two case expressions.
For example, the CASE expression would evaluate as:
SQL> SELECT
2 CASE
3 WHEN TO_CHAR(SYSDATE, 'DY') BETWEEN '1' AND '5'
4 THEN TO_DATE(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY')
5 ||' 08:00:00 PM', 'MM/DD/YYYY HH:MI:SS PM')
6 ELSE TO_DATE(TO_CHAR(TRUNC(SYSDATE), 'MM/DD/YYYY')
7 ||' 01:00:00 PM', 'MM/DD/YYYY HH:MI:SS PM')
8 END my_time
9 FROM dual;
MY_TIME
----------------------
11/24/2015 01:00:00 pm
The above example check the DAY for SYSDATE, and depending on it returns a datetime value.
using the above example, since you have two different datetime values to be compared as a date range condition, you will need two CASE expressions in your WHERE clause.
WHERE date_column
BETWEEN
CASE
WHEN TO_CHAR(date_column, 'DY') BETWEEN '1' AND '5'
THEN
TO_DATE(TO_CHAR(
TRUNC(date_column), 'MM/DD/YYYY')
||' 09:00:00 AM', 'MM/DD/YYYY HH:MI:SS PM')
ELSE
TO_DATE(TO_CHAR(
TRUNC(date_column), 'MM/DD/YYYY')
||' 09:00:00 AM', 'MM/DD/YYYY HH:MI:SS PM')
END
AND
CASE
WHEN TO_CHAR(date_column, 'DY') BETWEEN '1' AND '5'
THEN
TO_DATE(TO_CHAR(
TRUNC(date_column), 'MM/DD/YYYY')
||' 08:00:00 PM', 'MM/DD/YYYY HH:MI:SS PM')
ELSE
TO_DATE(TO_CHAR(
TRUNC(date_column), 'MM/DD/YYYY')
||' 01:00:00 PM', 'MM/DD/YYYY HH:MI:SS PM')
END

Oracle SQL Group By a String Aggregated Field

I'm having a problem grouping a field in my query. Here is an example of what I'm talking about:
Example:
AIR_DT DOL_GAP_TIME MATL_SIZE
15-JAN-15 8:00 AM 30
15-JAN-15 8:00 AM 25
15-JAN-15 9:00 AM 5
15-JAN-15 9:00 AM 10
15-JAN-15 9:00 AM 5
15-JAN-15 9:00 AM 20
Those with same time should be grouped as one, summing up their matl_size
Expected output:
AIR_DT DOL_GAP_TIME MATL_SIZE
15-JAN-15 8:00 AM 55
15-JAN-15 9:00 AM 40
Here is my SQL:
SELECT
a.air_dt,
TRIM(SUBSTR(TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss AM'),12,2))
|| ':00 '
|| TRIM(SUBSTR (TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss AM'),
21, 2)) dol_gap_time, e.matl_size
FROM order_implem_dtl_broadcast a, matl_mstr b, matl_size_mstr e
WHERE a.matl_id = b.matl_id
AND b.matl_size_id = e.matl_size_id
AND a.air_dt LIKE '%15-JAN-15%'
GROUP BY a.air_dt, a.dol_pref_start_time, e.matl_size
ORDER BY a.air_dt, a.dol_pref_start_time;
Thank you for helping in advance!
Based on your sample data, this should do what you want:
select AIR_DT, DOL_GAP_TIME, sum(MATL_SIZE)
from table t
group by AIR_DT, DOL_GAP_TIME;
However, I have no idea what this has to do with the query in the question.
OK let's start with your initial query:
SELECT
a.air_dt,
TRIM(SUBSTR(TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss AM'),12,2))
|| ':00 '
|| TRIM(SUBSTR (TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss AM'), 21, 2)) dol_gap_time, e.matl_size
FROM order_implem_dtl_broadcast a, matl_mstr b, matl_size_mstr e
WHERE a.matl_id = b.matl_id
AND b.matl_size_id = e.matl_size_id
AND a.air_dt LIKE '%15-JAN-15%'
GROUP BY a.air_dt, a.dol_pref_start_time, e.matl_size
ORDER BY a.air_dt, a.dol_pref_start_time;
I see a couple of problems. One, you're grouping by e.matl_size even though that is the column you want to SUM(). You don't want it in the GROUP BY. Second, your manner of getting the time from dol_pref_start_time is really odd. It looks like you want to round down to the hour, then just get the hour plus whether it is AM or PM. So this:
TRIM(SUBSTR(TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss AM'),12,2))
|| ':00 '
|| TRIM(SUBSTR (TO_CHAR (a.dol_pref_start_time, 'mm/dd/yyyy hh:mi:ss AM'), 21, 2)) dol_gap_time
can simply be this:
TO_CHAR(TRUNC(a.dol_pref_start_time, 'HH'), 'HH:MI AM') AS dol_gap_time
Third, are your dates stored as dates? If so, why are you doing this?
AND a.air_dt LIKE '%15-JAN-15%'
It would be far better to do this:
AND TRUNC(a.air_dt) = date'2015-01-15'
or, if you have an index on a.air_dt, this:
AND a.air_dt >= date'2015-01-15'
AND a.air_dt < date'2015-01-16'
Putting this all together, we get something like this (note that I've also converted your joins to ANSI SQL joins):
SELECT TRUNC(a.air_dt) AS air_dt
, TO_CHAR(TRUNC(a.dol_pref_start_time, 'HH'), 'HH:MI AM') AS dol_gap_time
, SUM(e.matl_size) AS matl_size
FROM order_implem_dtl_broadcast a INNER JOIN matl_mstr b
ON a.matl_id = b.matl_id
INNER JOIN matl_size_mstr e
ON b.matl_size_id = e.matl_size_id
WHERE a.air_dt >= date'2015-01-15'
AND a.air_dt < date'2015-01-16'
GROUP BY TRUNC(a.air_dt), TO_CHAR(TRUNC(a.dol_pref_start_time, 'HH'), 'HH:MI AM')
ORDER BY air_dt, TO_DATE(dol_gap_time, 'HH:MI AM'); -- using aliases in the ORDER BY, converting dol_gap_time to DATE for sorting

start/end date and time in oracle sql query

I need a query output like the below table;
This is a primary entry to a table and these records will be modified by a third party program which I have no control. Can anyone suggest a good sample?
ID | DATEIN | DATEOUT | STATUS
1 02.02.2014 00:00:00 02.02.2014 23:59:59 1
2 03.02.2014 00:00:00 03.02.2014 23:59:59 0
I tried
SELECT To_Char(To_Date(SYSDATE), 'dd-MM-yyyy hh:mm:ss PM'),
To_Char(date_add(To_Date(SYSDATE +1), INTERVAL -1 SECOND), 'dd-MM-yyyy hh:mm:ss PM')
FROM dual
but this query throws an error ORA-00907: missing right parenthesis.
There is no need for PM if you want it to be in 24-hour format. And pay attention to the mask for minutes, it is mi, not mm as in your query. Also as already mentioned no need to convert SYSDATE to date as it is already of that datatype:
SELECT to_char(to_date(SYSDATE), 'dd-mm-yyyy HH24:mi:ss') date_in,
to_char(to_date(SYSDATE + 1) - INTERVAL '1' SECOND, 'dd-mm-yyyy HH24:mi:ss') date_out
FROM dual;
DATE_IN DATE_OUT
------------------- -------------------
11-03-2014 00:00:00 11-03-2014 23:59:59
You can do away with DATE_ADD and TO_DATE functions (SYSDATE is already a DATE, no need of conversion ) , and also use mi to show minute instead of mm which is format specifier for month as in:
SELECT To_Char(SYSDATE, 'dd-MM-yyyy hh:mi:ss PM'),
To_Char((SYSDATE + 1) + INTERVAL '-1' SECOND, 'dd-MM-yyyy hh:mi:ss PM')
FROM dual
I am not clear what you are trying to achieve from the above query but if parenthesis is your only problem then you gotta hit the query:
SELECT To_Char(To_Date((SYSDATE), 'dd-MM-yyyy hh:mm:ss PM')),
To_Char(date_add(To_Date(SYSDATE +1), INTERVAL -1 SECOND), 'dd-MM-yyyy hh:mm:ss PM')
FROM dual