ORA-01427 while UPDATE self-join ORACLE - oracle

two tables, each has employee_id and manager_id which links to employee_id Tables have different employee_id.
UPDATE employee u
SET u.manager_id = (SELECT m.id
FROM employee e
JOIN old_db.employees oe ON e.last_name = oe.last_name
JOIN old_db.employees om ON oe.manager_id = om.employee_id
INNER JOIN employee m ON m.last_name = om.last_name
WHERE e.id = u.id)
WHERE manager_id IS NULL;
gives
ERROR at line 2:
ORA-01427: single-row subquery returns more than one row
I've tried rownum=1 but this makes all manager_id same.
Select query with one given employee_id returns one value
SQL> SELECT m.id
2 FROM employee e
3 JOIN old_db.employees oe ON e.last_name = oe.last_name
4 JOIN old_db.employees om ON oe.manager_id = om.employee_id
5 INNER JOIN employee m ON m.last_name = om.last_name
6 WHERE e.id = 1805;
ID
----------
1804

Well the root cause of problem is in table employees or in table employee last_name are not unique. And when you join table on last name you get more then one row. You may check it with next query:
SELECT e.id, count(*), count(distinct m.id)
FROM employee e
JOIN old_db.employees oe ON e.last_name = oe.last_name
JOIN old_db.employees om ON oe.manager_id = om.employee_id
INNER JOIN employee m ON m.last_name = om.last_name
GROUP BY e.id;
May be exists more suitable column to join it for example employee_id if so you query may be rewritten to:
UPDATE employee u
SET u.manager_id = (SELECT oe.manager_id
FROM old_db.employees oe
WHERE oe.employee_id = u.id)
WHERE manager_id IS NULL;

Related

Oracle HR Schema. Selecting of max salary from Employees

I need to select city, max salary in the city and employee name whose salary is max from Oracle HR Schema.
I try to do below code, but city name repeats:
select l.city, e.last_name, e.salary from locations l
inner join departments d on l.location_id = d.location_id
inner join employees e on d.department_id = e.department_id
and e.salary = (select max(salary) from employees where department_id = d.department_id)
group by l.city, e.last_name, e.salary
order by e.salary;
What is wrong with my code?
I've attached result, which I need.Correct SQL result
You can use the DENSE_RANK analytic function (which will return all employees with the maximum salary per city):
SELECT city,
last_name,
salary
FROM (
SELECT l.city,
e.last_name,
e.salary,
DENSE_RANK() OVER (
PARTITION BY l.location_id
ORDER BY e.salary DESC
) AS rnk
FROM locations l
INNER JOIN departments d
ON l.location_id = d.location_id
INNER JOIN employees e
ON d.department_id = e.department_id
)
WHERE rnk = 1;
or aggregation with KEEP (which will only return one employee with the maximum salary and the maximum last name per location):
SELECT MAX(l.city) AS city,
MAX(e.last_name) KEEP ( DENSE_RANK LAST ORDER BY e.salary ) AS last_name,
MAX(e.salary) AS salary
FROM locations l
INNER JOIN departments d
ON l.location_id = d.location_id
INNER JOIN employees e
ON d.department_id = e.department_id
GROUP BY
l.location_id
What is wrong with my code?
You are correlating on department_id = d.department_id and not on the location (or city name; however, don't aggregate on the city name as there could be two different locations with the same name).

Group by a subquery in Oracle

Say I have a query such as the following:
SELECT
EmployeeName,
DepNo,
sum(wages)
FROM
Employees
GROUP BY
EmployeeName,
DepNo
Then I have some data in another table called Departments such as:
DepNo DepName
1 Accountants
2 HR
3 IT
How could I swap the Employee.DepNo to be the Department.DepName?
I tried adding a nested select but I ran into an issue when grouping:
SELECT
EmployeeName,
(SELECT DISTINCT DepName FROM Departments WHERE Employees.DepNo = Departments.DepNo) AS DepName,
sum(wages)
FROM
Employees
GROUP BY
EmployeeName,
DepName
Don't use a subquery, just JOIN to the other table and then return the column in the SELECT:
SELECT E.EmployeeName,
D.DepName,
SUM(Wages) AS Wages
FROM Employees E
JOIN Departments D ON E.DepNo = D.DepNo
GROUP BY E.EmployeeName,
D.DepName
Since you are asking for another answer, You may update your query to -
SELECT
EmployeeName,
(SELECT DISTINCT DepName
FROM Departments
WHERE Employees.DepNo = Departments.DepNo) AS DepName,
sum(wages)
FROM
Employees
GROUP BY
EmployeeName,
Employees.DepNo

Report Job difference in HR schema

I'm new to Oracle and try to practice with HR schema. For example I want to report of those whose job is different from the previous job.
Employee name in employees table and job history in job_history table.
I think the following query will help. (I am considering that current JOB_ID is present in the EMPLOYEES table and you want to compare it with the latest previous JOB_ID from JOB_HISTORY table for the employee)
SELECT E.*, JH.LATEST_PREV_JOB_ID
FROM EMPLOYEES E
JOIN (SELECT FIRST_VALUE(JH.JOB_ID) OVER (PARTITION BY JH.EMPLOYEE_ID
ORDER BY JH.START_DATE DESC NULLS LAST) AS LATEST_PREV_JOB_ID,
JH.EMPLOYEE_ID
FROM JOB_HISTORY JH) JH
ON E.EMPLOYEE_ID = JH.EMPLOYEE_ID
WHERE E.JOB_ID <> JH.LATEST_PREV_JOB_ID
----- Update
You want the query without partition by clause (i.e. without WINDOWS function), We can use the NOT EXISTS as follows:
SELECT E.*, JH.LATEST_PREV_JOB_ID
FROM EMPLOYEES E
JOIN (SELECT JH.JOB_ID AS LATEST_PREV_JOB_ID,
JH.EMPLOYEE_ID
FROM JOB_HISTORY JH
WHERE NOT EXISTS (SELECT 1 FROM JOB_HISTORY JHIN
WHERE JHIN.EMPLOYEE_ID = JH.EMPLOYEE_ID
AND JHIN.START_DATE > JH.START_DATE)) JH
ON E.EMPLOYEE_ID = JH.EMPLOYEE_ID
WHERE E.JOB_ID <> JH.LATEST_PREV_JOB_ID
If I understood right your question, then the answer maybe something like this:
select
e.first_name,
e.last_name,
e.job_id as prev_job,
jh.job_id as last_lob
from
employees e,
job_history jh,
(select
employee_id,
max(end_date) as max_end_date
from
job_history
group by
employee_id
) t
where
(jh.employee_id = e.employee_id) and
(jh.job_id <> e.job_id) and
(jh.end_date = t.max_end_date) and
(t.employee_id = jh.employee_id)

Getting ORA-00918: column ambiguously defined error on 10g but works in 11g

select distinct p.id,
format_name(p.fname, p.lname,'local000000000000001') full_name,
p.username,
p.person_no,
jobinfo.name,
company.name2,
company.name,
dom.name,
per_mgr.username,
a.name
from cmt_person p
inner join fgt_locale loc on loc.id='local000000000000001'
left outer join tpt_company company on p.company_id = company.id
left outer join tpt_ext_job_type jobinfo on p.jobtype_id = jobinfo.id AND jobinfo.locale_id=loc.id
inner join fgt_domain dom on p.split = dom.id
left outer join fgt_gen gen on gen.id1 = p.id and gen.TYPE = 301 and gen.str2 IS NULL
left outer join fgt_ext_admin_managed_lov a on a.id = gen.id2 and a.locale_id = loc.id
left outer join cmt_person per_mgr on per_mgr.id = p.manager_id
inner join fgt_address a on a.owner_id = p.id
where ( p.terminated_on is null or p.terminated_on >= sysdate)
and( (p.type = 100 and p.split in ('domin000000000000007','domin000000000001107','domin000000000001108','domin000000000001109','domin000000000001104','domin000000000001103','domin000000000001106','domin000000000001105','domin000000000000001','domin000000000001102','domin000000000001110'))
or (p.type = 200 and p.split in ('domin000000000000007','domin000000000001107','domin000000000001108','domin000000000001109','domin000000000001104','domin000000000001103','domin000000000001106','domin000000000001105','domin000000000000001','domin000000000001102','domin000000000001110')) )
AND 1=1
AND lower(p.status) = lower('A')
AND lower(a.country) like lower('USA' || '%')
AND p.type in (decode('1','1',100,'2',200,'0',p.type))
AND p.manager_id in ('emplo000000000034578')
ORDER BY 2,3,4,5,6,7,8,9,10
This is the query I have defined table alias for all tables
Do I need column aliases for following columns for 10g?
jobinfo.name ,
company.name2 ,
company.name ,
dom.name
Two tables share the same alias ("a"): fgt_ext_admin_managed_lov and fgt_address. Change it, as that won't work:
SQL> select a.deptno
2 from dept a, emp a;
select a.deptno
*
ERROR at line 1:
ORA-00918: column ambiguously defined
SQL>
Look at below code :-
left outer join fgt_ext_admin_managed_lov a <<<
..
..
inner join fgt_address a <<<<
You have used same alias name for both tables. Change it to any other alias name.

Oracle Procedure not a group by function error 00979

i have written this procedure to select employees from employee table and corresponding sum of total quantity sold by purchases table. my procedure is created without any error but the block is not working
Change the query in your procedure to
SELECT e.NAME, SUM(p.QTY)
INTO emp_name, total_qty
FROM PURCHASES p
INNER JOIN EMPLOYEES e
ON e.EID = p.EID
WHERE p.EID = empno
GROUP BY e.NAME
Basically, use WHERE instead of HAVING. If you're really dying to use HAVING you can use
SELECT p.EID, e.NAME, SUM(p.QTY)
INTO emp_name, total_qty
FROM PURCHASES p
INNER JOIN EMPLOYEES e
ON e.EID = p.EID
GROUP BY p.EID, e.NAME
HAVING p.EID = empno
To use HAVING the field it refers to must be in the results, and thus must be in the GROUP BY.
Best of luck.

Resources