Send mail when transaction time is behind system time on UNIX - oracle

I have a query to run on oracle that gives output as sid,serial#,transaction start time,sql_id,transaction id.
What I need to do is, whenever a transaction's start time is more than 1 hour behind the system time, I need to run another query with that sql_id and send it as an email.
How do I compare this time output from ORACLE sql and compare it with the system time?
I need to automate this process and add it to the cron on UNIX.
Please help!

The function SYSDATE returns the current system date. When you subtract two dates, you get a difference measured in days. Multiply by 24 and you get a difference in terms of hours.
SELECT *
FROM v$transaction
WHERE (sysdate - start_date)*24 > 1
will give you the transactions that started more than 1 hour ago. You can also use interval arithmetic if you find that clearer.
SELECT *
FROM v$transaction
WHERE sysdate - interval '1' hour > start_date

Related

Not enough memory for CONNECT BY operation when using interval '3' minute

If I use the following code for my report it works fine:
select
to_date(substr(:P1_START,1,15), 'YYYY-MM-DD"T"HH24MI') + (rownum/480) s
from dual
connect by
to_date(substr(:P1_START,1,15), 'YYYY-MM-DD"T"HH24MI') + (rownum/480) <= to_date(substr(:P1_END,1,15), 'YYYY-MM-DD"T"HH24MI')
But if I change (rownum/480) to interval '3' minute I get a ORA-30009: Not enough memory for CONNECT BY operation error on the report
select
to_date(substr(:P1_START,1,15), 'YYYY-MM-DD"T"HH24MI') + interval '3' minute s
from dual
connect by
to_date(substr(:P1_START,1,15), 'YYYY-MM-DD"T"HH24MI') + interval '3' minute <= to_date(substr(:P1_END,1,15), 'YYYY-MM-DD"T"HH24MI')
Is they a way I can keep using interval '3' minute?
Well... the problem is that the statement is generating so much rows that all the computing memory you have available is used up. Do you need that many rows ? Have you checked how many rows oracle is trying to generate for you when it is throwing that error ? If you double the memory and then you run the same query where the interval between start and end date is double as large it will also error out.
Do you really need to generate this table on the fly with a CONNECT BY statement ? Maybe you could also just create an actual table with 3 minute intervals and join to that table in your query. It would give you the same functionality and be a lot more efficient from a db perspective: that table can be indexed and it would be shared across user sesssions.

Where results displayed are less than current time

On Oracle SQL Developer, I'm looking to write a where function that gives me the last 7 days of data. I can write that part myself fine, but the extra part that I need to add on to the end is that I only want results that are for the past 7 days before my current time.
For example, if I query at 14:00 today, I would want it to return results for the past 7 days with data only up until 14:00, as opposed to the full day.
Is this possible?
SYSDATE is the Oracle built in date function that supplies the current date / time accurate to 1 second. All you have to do is:
select *
from whatever
where whatever.datecol between sysdate - 7 and sysdate;

Validating Date Prompt To be less than Current Date OBIEE

I have a requirement to create two validations on the date prompt:
1) The From Date has to be less than To Date
2) The To Date has to be less than or equal to current date
I created a conditional analysis wherein From Date is < To Date, which works, but when I try to create an advanced filter wherein #To_Date <= Current_Date I am getting an error.
Error getting drill information: SELECT date'2016-08-24' saw_0 FROM "Workforce Management - Processed Time Cards Real Time" WHERE(date'#{To_Date}' <= (SELECT VALUEOF("CURRENT_DATE_REP_OTBI") FROM "Workforce Management - Processed Time Cards Real Time" FETCH FIRST 1 ROWS ONLY))
If anyone can help solve this, it'd be really helpful!
Thanks
You need to add a default value when referencing presentation variables in logical SQL queries or formulas. Especially if these are dates.
I created an analysis based on the following LogicalSQL and it worked.
SELECT date'2016-08-26' saw_0 from "subject_area" WHERE (date
#{to_date}{'2016-08-26'} < CURRENT_DATE)
Notice the following:
The presentation variable #{to_date} goes with a default value (noted by the second curly brackets). This helps OBIEE to validate the query. Failing to add the default value will give you the "getting drill information" error.
Instead of a session RPD variable, you can use CURRENT_DATE. It simplifies the query.
The above query will return the date in the SELECT clause, but if the to_date is greater than CURRENT_DATE will return no data.

complex sql query for finding the average working time of a person in office

I need to retrieve using an oracle based query the working time of an employee which is the time coming in and time going out for an employee based on his transactions in the transaction table.
The transaction table has a date-time field which can be used for this purpose.
The steps involved would be as follows:
1) find the first transaction on a date and the last transaction on the same date - that would be his time in and timeout for that date
2) calculate the overall time-in as the avg of all time-ins on each date, similarly do for time-out
Transaction table is as follows: transctn(transid, resourceid, event, currentdate)
The second requirement is to find the average transactions performed each day, which is basically find the count of transids for each day and then average of that.
The final answer should be, when a userid is provided the query the return result is:
frequent working time(based on average): 9:43 am - 6:45 pm
average transactions performed/day = 43
How do I write the above requirement in oracle SQL or more smartly using Hibernate if Transctn is my Domain class
I have something like this:
select 'frequent working time: '
||(select rtrim(to_char(min(currentdate),'hh:mi pm')) from transctn)
||' - '||(select rtrim(to_char(max(currentdate),'hh:mi pm')) from transctn)
||', average transactions performed/day = '
||(select rtrim(to_char(count(distinct transid)/
count(distinct(to_char(currentdate,'rrmmdd')))) from transctn)
from dual
Firstly, your query has lots of selects from the same table stuck together, which isn't efficient, and makes it harder to read than necessary. And the rtrim isn't doing anything as you've already dictated the format. What you have can be rewritten as:
select 'frequent working time: '|| to_char(min(currentdate),'hh:mi pm')
||' - '|| to_char(max(currentdate),'hh:mi pm'),
'average transactions performed/day = '
|| to_char(count(distinct transid)
/count(distinct to_char(currentdate,'rrmmdd')))
from transctn;
But this isn't averaging properly, and isn't for a specific user. I'm join to assume this is homework and in the usual spirit of the site, try to give you pointers rather than the complete answer...
1) find the first transaction on a date and the last transaction on
the same date - that would be his time in and timeout for that date
You're not far off here, but you're breaking down by date. To get the time-in and time-out for every user, for each day, you could use:
select resourceid, trunc(currentdate), min(currentdate), max(currentdate)
from transctn
group by resourceid, trunc(currentdate)
order by resourceid, trunc(currentdate);
2) calculate the overall time-in as the avg of all time-ins on each
date, similarly do for time-out
You can't average dates directly in Oracle; you'd get ORA-00932: inconsistent datatypes: expected NUMBER got DATE. There are various ways to achieve the effect, you just need to figure out a safe way to treat the date - or more specifically here the time part - as a number. For example, you could treat the time portion as the difference between the actual time and the start of the day, which Oracle returns as a number:
select avg(min(currentdate) - trunc(currentdate)),
avg(max(currentdate) - trunc(currentdate))
from transctn
group by trunc(currentdate);
But you than have to translate that fractional number back into something recognisable. One way of doing that is to add the number to an arbitrary fixed date, and then just extract the time part as a string as you were already doing:
select to_char(date '2000-01-01' + avg(min(currentdate) - trunc(currentdate)),
'HH:MI pm') as avg_time_in,
to_char(date '2000-01-01' + avg(max(currentdate) - trunc(currentdate)),
'HH:MI pm') as avg_time_out
from transctn
group by trunc(currentdate);
This look messy and you might find a better way to do it. If it is homework then I would assume you've been taught methods for doing this sort of thing, or something that can be adapted to be applicable.
This is still for all resources, so you'll need to add a filter to restrict to one user ID. Hopefully this gives you some ideas for tackling the second requirement as well.

Oracle 10g - Determine the average of concurrent connections

Is it possible to determine the average of concurrent connections on a 10g large database installation?
Any ideas??
This is probably more of a ServerFault question.
On a basic level, you could do this by regularly querying v$session to count the number of current sessions, store that number somewhere, and average it over time.
But there are already good utilities available to help with this. Look into STATSPACK. Then look at the scripts shown here to get you started.
Alternatively you could install a commercial monitoring application like Spotlight on Oracle.
If you have Oracle Enterprise Manager set up you can create a User Defined Metric which records SELECT COUNT(*) FROM V$SESSION. Select Related Links -> User Defined Metrics to set up a new User Defined Metric. Once it collects some data you can get the data out in raw form or it will do some basic graphing for you. As a bonus you can also set up alerting if you want to be e-mailed when the metric reaches a certain value.
The tricky bit is recording the connections. Oracle doesn't do this by default, so if you haven't got anything in place then you won't have a historical record.
The easiest way to start recording connections is with Oracle's built in audit functionality. It's as simple as
audit session
/
We can see the records of each connection in a view called dba_audit_session.
Now what? The following query uses a Common Table Expression to generate a range of datetime values which span 8th July 2009 in five minute chunks. The output of the CTE is joined to the audit view for that date; A count is calulated for each connection which spans a five minute increment.
with t as
( select to_date('08-JUL-2009') + ((level-1) * (300/86400)) as five_mins
from dual connect by level <= 288)
select to_char(t.five_mins, 'HH24:MI') as five_mins
, sum(case when t.five_mins between timestamp and logoff_time
then 1
else 0 end) as connections
from t
, dba_audit_session ssn
where trunc(ssn.timestamp) = to_date('08-JUL-2009')
group by to_char(t.five_mins, 'HH24:MI')
order by t.five_mins
/
You can then use this query as the input into a query which calculates the average number of connections.
This is a fairly crude implementation: I choose five minute increments out of display considerations , but obviously the finer grained the increment the more accurate the measure. Be warned: if you make the increments too fined grained and you have a lot of connections the resultant cross join will take a long time to run!

Resources