How to query for Inactive Employees using BI Publisher in Oracle Fusion? - oracle

I'm new to BI Publisher and I'm using it through Oracle Fusion Applications.
I am trying to make a report relating to the Inactive Employees in an organization. However I am unable to figure out how to query for an inactive or terminated employee.
I initially used this query:
SELECT PERSON_ID, PERSON_NUMBER, EFFECTIVE_START_DATE, EFFECTIVE_END_DATE
FROM PER_ALL_PEOPLE_F
WHERE TRUNC(SYSDATE) NOT BETWEEN TRUNC(EFFECTIVE_START_DATE) AND TRUNC(EFFECTIVE_END_DATE)
My other considerations were attributes from the PER_ALL_ASSIGNMENTS_M table including PRIMARY_WORK_RELATION_FLAG, PRIMARY_ASSIGNMENT_FLAG and ASSIGNMENT_TYPE considering that the employee's assignment details would help somehow. However I was unsuccessful.
I wanted to know if there was any other proper way to query for inactive employees. Is there any particular attribute in any table which would tell me for certain that an employee is active or terminated? When an employee is terminated in Oracle Fusion, which all table attributes get affected?
Thank you for your help.

The easiest way to do this is simply :
SELECT * FROM YourTable t
WHERE TRUNC(t.END_DATE) <= trunc(sysdate)
Some times there is also an indication column like IS_ACTIVE or something. You can also consider adding it, and simply updating it to 1 for all the records returned from the above query.
Other then that, we can't really help you. We don't know your table structures, we don't know what data you store in them and which column indicates what .

I have found what i was looking for. ASSIGNMENT_STATUS_TYPE='INACTIVE' was what I needed (As mentioned in the question, this solution is without considering 'EFFECTIVE_END_DATE') Getting the 'latest' assignment status of an employee was what I needed to find. The following query works if the employee has only one Assignment assigned.
SELECT PAPF.PERSON_ID, PAPF.PERSON_NUMBER
FROM PER_ALL_PEOPLE_F PAPF, PER_ALL_ASSIGNMENTS_M PAAM
WHERE 1=1
AND TRUNC(PAAM.EFFECTIVE_START_DATE) = (SELECT MAX(TRUNC(PAAM_INNER.EFFECTIVE_START_DATE))
FROM PER_ALL_ASSIGNMENTS_M PAAM_INNER
WHERE PAAM_INNER.PERSON_ID=PAAM.PERSON_ID
GROUP BY PAAM_INNER.PERSON_ID)
AND PAPF.PERSON_ID=PAAM.PERSON_ID
AND PAAM.PRIMARY_FLAG='Y'
AND PAAM.ASSIGNMENT_STATUS_TYPE='INACTIVE'
AND TRUNC(SYSDATE) BETWEEN PAAM.EFFECTIVE_START_DATE AND PAAM.EFFECTIVE_END_DATE
AND TRUNC(SYSDATE) BETWEEN PAPF.EFFECTIVE_START_DATE AND PAPF.EFFECTIVE_END_DATE
ORDER BY 1 ASC
I had help from the Oracle Support Community to get to an answer.
Link: https://community.oracle.com/message/14000136#14000136
However in a case where an employee was given an assignment say starting from year 2000 and ending at 20015, then another assignment starting from 2016 till present, the above query will return one record of the said employee as 'Inactive' if the Max Effective_start_date condition is not checked. (Since one became Inactive on 2015), even though her current Assignment status is 'Active' and she is currently not terminated.
In such a case, it is wise to retrieve the record with the greatest 'EFFECTIVE_START_DATE' from the PER_ALL_ASSIGNMENTS_M table, ie, checking if EFFECTIVE_START_DATE = MAX(EFFECTIVE_START_DATE)

Related

SQL Developer Distinct gives ORA-00936

I try to create a query which gives me back how many customer has been registered to our system (using the REGISTERED_ID). However when a customer registrates he can then registrate again with a different car. I want to give back the amount of registers by month. I count the X__INSDATE because basicly I can count anything, all I need is a number. The error points to the DISTINCT, I tried to use having instead of where, but I may missed something.
I use Oracle SQL Developer 4.0.0.12
SELECT
TRUNC(X__INSDATE, 'MONTH') as HONAP,
COUNT(X__INSDATE),
DISTINCT REGISTERED_ID
FROM
DATABASE.data_history
WHERE
DATABASE.data_history.X__INSDATE >= to_date('2013-JÚL. -01', 'YYYY-MON-DD')
GROUP BY TRUNC(X__INSDATE, 'MONTH') ORDER BY HONAP;
Thank you for your help!
You need to apply an aggregate function to all the clauses not on the grup by.
Try with:
SELECT
TRUNC(X__INSDATE, 'MONTH') as HONAP,
COUNT(X__INSDATE),
COUNT(DISTINCT REGISTERED_ID)
Or by grouping as well by REGISTERED_ID

How to insert while avoiding unique constraints with oracle

We have a process that aggregates some data and inserts the results into another table that we use for efficient querying. The problem we're facing is that we now have multiple aggregators running at roughly the same time.
We use the original records id as the primary key in this new table - a unique constraint. However, if two aggregation processes are running at the same time, one of them will error with a unique constraint violation.
Is there a way to specify some kind of locking mechanism which will make the second writer wait until the first is finished? Alternatively, is there a way to tell oracle to ignore that specific row and continue with the rest?
Unfortunately it's not practical to reduce the aggregation to a single process, as the following procedures rely on an up to date version of the data being available and those procedures do need to scale out.
Edit:
The following is my [redacted] query:
INSERT INTO
agg_table
SELECT
h.id, h.col, h.col2
FROM history h
JOIN call c
ON c.callid = h.callid
WHERE
h.id > (SELECT coalesce(max(id),0) FROM agg_table)
It is possible run an INSERT statement with an error logging clause. The example from the Oracle docs is as follows:
INSERT INTO dw_empl
SELECT employee_id, first_name, last_name, hire_date, salary, department_id
FROM employees
WHERE hire_date > sysdate - 7
LOG ERRORS INTO err_empl ('daily_load') REJECT LIMIT 25
Alternatively, you could try using a [MERGE][2] statement. You would be merging into the summary table with a select from the detail table. If a match is not found, you INSERT and if it is found you would UPDATE. I believe this solution will handle your concurrency issues, but you would need to test it.
have a look at FOR UPDATE clause. If you correctly write the SELECT statement with FOR UPDATE clause within a transaction before your update/insert statements you will be able to "lock" the required records
Serialising the inserts is probably the best way, as there's no method that will get you round the problem of the multiple inserts being unable to see what each one is doing.
DBMS_Lock is probably the appropriate serialisation mechanism.

Refreshable on commit materialized view using MAX()

I'm being hit hard by the entity-attribute-value antipattern. Some day, years ago, a guy decided that DDL wasn't sexy, and wanted to develop something "flexible enough" to keep information about people. He ignored the fact that people uses to have at least some basic attributes, as name, date of birth, and the like. Not only that, he put a bunch of (side-effects-ridden) PL/SQL packages on top of that schema. The thing managed to be a key subsystem in which other applications relied on.
Fast forward some years and 20 million rows. The guy isn't at the company anymore, and I have to deal with this. I need to implement some basic searches that right now would require multiple inner joins and just take forever for some cases. Rewriting the whole thing it's not possible, so I want to "pivot" the most important attributes.
I thought that materialized views could be a viable alternative, but I need some guidance, since I have never used them. I would like to get a table like this:
select
uid,
max(case when att = 'NAME' then UPPER(value) end) name,
max(case when att = 'SURNAME' then UPPER(value) end) surname,
max(case when att = 'BIRTH' then DATEORNULL(value) end) birth,
....,
count(*) cnt
from t
group by uid
as I understand reading Oracle docs, I should be able to create a "REFRESHABLE ON COMMIT" materialized view with MAX() if the query has no where clause.
But can't get it to work. I've tried:
create materialized view log on t WITH SEQUENCE,ROWID,(value) INCLUDING NEW VALUES;
create materialized view t_view
refresh fast on commit
as
select
uid,
max(case when att = 'NAME' then UPPER(value) end) name,
max(case when att = 'SURNAME' then UPPER(value) end) surname,
max(case when att = 'BIRTH' then DATEORNULL(value) end) birth,
count(*) cnt
from t
group by uid
It works for inserts, but not for updates. I see that is capable of these things:
REFRESH_COMPLETE
REFRESH_FAST
REFRESH_FAST_AFTER_INSERT
but I think I should see also REFRESH_FAST_AFTER_ONETAB_DML. Any ideas?
Update: Output of dbms_mview.explain_mview
REFRESH_COMPLETE |Y|
REFRESH_FAST |Y|
REFRESH_FAST_AFTER_INSERT |Y|
REFRESH_FAST_AFTER_ONETAB_DML|N|mv uses the MIN or MAX aggregate functions
REFRESH_FAST_AFTER_ANY_DML |N|see the reason why REFRESH_FAST_AFTER_ONETAB_DML is disabled
REFRESH_FAST_PCT |N|PCT is not possible on any of the detail tables in the mater
The MV_CAPABILITIES_TABLE.MSGTXT is wrong, what you really need to do is replace case with decode.
When I tried this on 11g I got the message CASE expressions present in materialized view. Changing it to use decode fixed it on both 10g and 11g.

Oracle query getting ORA-00907: missing right parenthesis

I've read through the other missing right parenthesis questions and haven't found an answer to my problem. I assume it is a syntax error cutting things off before the end (I'm not really an Oracle guy) but I don't know where it is. The query is supposed to pull the customer ID and the latest year there is a record for that customer. The parameters are a customer ID number (unique by district but different from the organizational one), the district, and the year being searched. If there is no record for the searched year for that district, no records should be returned.
SELECT DISTINCT CUSTOMER.CUSTOMER_ID_ALT, tblMaxYear.maxYear
FROM CUSTOMER CROSS JOIN
(SELECT to_char(Max(tblYr.FISCAL_YEAR), 'YYYY') AS maxYear
FROM CUSTOMER AS tblYr
WHERE tblYr.DISTRICT_KEY= :district
AND tblYr.CUSTOMER_ID= :cust) tblMaxYear
WHERE CUSTOMER.DISTRICT_KEY=:district
AND CUSTOMER.CUSTOMER_ID= :cust
AND to_char(CUSTOMER.FISCAL_YEAR, 'YYYY') = :prmYear
Remove the AS in:
FROM CUSTOMER AS tblYr
AS can be used for column aliasing, not table aliasing

CTE With Insert In Oracle

i am running a query in oracle with CTE.
When i execute the query it works fine in select statement but when i use insert statement it takes ample of time to execute.Any help here is the code
INSERT INTO port_weeklydailypricesTest (co_code,start_dtm,end_dtm)
SELECT * FROM
(
WITH CTE(co_code, start_dtm, end_dtm) AS
(
SELECT co_code ,
CAST(NEXT_DAY(MIN(dlyprice_date),'FRIDAY')-6 AS DATE) start_dtm ,
CAST(NEXT_DAY(MIN(dlyprice_date),'FRIDAY') AS DATE) end_dtm
FROM feed_dlyprice
GROUP BY co_code
UNION ALL
SELECT co_code ,
CAST(TO_CHAR(end_dtm + INTERVAL '1' DAY,'DD-MON-YYYY') AS DATE),
CAST(TO_CHAR(end_dtm + INTERVAL '7' DAY,'DD-MON-YYYY') AS DATE)
FROM CTE
WHERE CAST(end_dtm AS DATE) <= TO_CHAR(TO_DATE(SYSDATE+1,'DD-MON-YYYY'))
)
SELECT co_code,start_dtm,end_dtm
FROM CTE
);
If, as you say, the performance of the SELECT on its own is satisfactory the problem must lie with the INSERT part of the statement.
There are a number of things which might cause an insert to run slow:
The most likely is the presence of a trigger on the target table which executes something very expensive.
Another possibility is that the insert is waiting on a locked resource (say some other process has an exclusive table level lock on the target table, or some other shared resource such as a code control table).
it could be a storage allocation issue, chaining or row migration, too many indexes or lots of derived columns.
perhaps it is down to hardware - underpowered network, dodgy interconnects, a bad disk.
This is by no means exhaustive. The items at the top are application issues which you should be able to investigate and resolve. The further down the list you go the more likely it is that you will need the assistance on an on-site DBA.

Resources