How to increase the salary of an employee based on the number of children in SQL ORACLE 10G? - sql

I have two tables: employee and dependent
Structure
- Table employee
Name Null? Type
EMPLOYEEID NOT NULL NUMBER(3)
LNAME NOT NULL VARCHAR2(15)
FNAME NOT NULL VARCHAR2(15)
POSITIONID NUMBER(1)
SUPERVISOR NUMBER(3)
HIREDATE DATE
SALARY NUMBER(6)
COMMISSION NUMBER(5)
DEPTID NUMBER(2)
QUALID NUMBER(1)
- Table Dependent
Name Null? Type
EMPLOYEEID NOT NULL NUMBER(3)
DEPENDENTID NOT NULL NUMBER(1)
DEPDOB NOT NULL DATE
RELATION NOT NULL VARCHAR2(8)
Data
- Table employee
EMPLOYEEID LNAME FNAME POSITIONID SUPERVISOR HIREDATE SALARY COMMISSION DEPTID QUALID
111 Smith John 1 15/04/60 265000 35000 10 1
246 Houston Larry 2 111 19/05/67 150000 10000 40 2
123 Roberts Sandi 2 111 02/12/91 75000 10 2
543 Dev Derek 2 111 15/03/95 80000 20000 20 1
433 McCall Alex 3 543 10/05/97 66500 20 4
135 Garner Stanley 2 111 29/02/96 45000 5000 30 5
200 Shaw Jinku 5 135 03/01/00 24500 3000 30
222 Chen Sunny 4 123 15/08/99 35000 10 3
- Table Dependent
EMPLOYEEID DEPENDENTID DEPDOB RELATION
543 1 28/09/58 Spouse
543 2 14/10/88 Son
200 1 10/06/76 Spouse
222 1 04/02/75 Spouse
222 2 23/08/97 Son
222 3 10/07/99 Daughter
111 1 12/12/45 Spouse
And I have two employees: One employee has one child, and the other has two children. I got it with the following query:
Query
SELECT employee.employeid, lname, fname, salary, dependent.relation
FROM employee INNER JOIN dependent
ON employee.employeeid = dependent.employeeid
WHERE dependent.relation = 'Daughter' OR dependent.relation = 'Son';
Result
EMPLOYEEID LNAME FNAME SALARY RELATION
543 Dev Derek 80000 Son
222 Chen Sunny 35000 Son
222 Chen Sunny 35000 Daughter
And my homework is increase the salary $ 100 per child, and I tried with the following code:
UPDATE employee
SET SALARY = salary + 100
WHERE employee.employeeid IN (
SELECT employee.EMPLOYEEID FROM employee INNER JOIN dependent
ON employee.employeeid = dependent.employeeid
WHERE dependent.relation = 'Daughter' OR dependent.relation = 'Son' );
But, i donĀ“t get the expect result. The employee "Chen" has two children, but his salary only increase once, no twice. Her final salary is $ 35100, no $ 35200.
Can anybody help me?

I can't test on Oracle version 10, but this should work fine:
Well, apparently, it doesn't work in Oracle 10 (though it does work correctly in Oracle 12). I added an alternative at the bottom of the post using merge that should work correctly.
update (
select e.salary,
d.childcnt * 100 as increase
from employee e
join (select d.employeeid, count(*) as childcnt
from dependent d
where d.relation in ('Son', 'Daughter')
group by d.employeeid) d
on d.employeeid = e.employeeid
) set salary = salary + increase
Here is another way of achieving the same thing using the merge command. This should work correctly in Oracle 10:
merge into employee dest
using (
select employeeid,
count(*) * 100 as increase
from dependent d
where relation in ('Son', 'Daughter')
group by employeeid
) src
on (src.employeeid = dest.employeeid)
when matched then
update set dest.salary = dest.salary + src.increase

Related

self join query

emp_id
emp
level
manager_id
manager
100
sam
1
100
sam
200
jack
2
100
sam
300
jill
2
100
sam
400
claire
3
200
jack
500
reed
3
300
jill
600
derrick
4
400
claire
700
bill
4
500
reed
I have a table with employees and their respective managers in column 'emp' and 'manager' respectively. The numbers in the 'level' column represent different levels within an organisation for the employees in column 'emp'.
How do i write a query to get the manager name from the previous level as an entry in step and so forth.
emp_id
emp
level
manager_id
manager
l1
l2
l3
l4
100
sam
1
100
sam
NULL
NULL
NULL
NULL
200
jack
2
100
sam
sam
NULL
NULL
NULL
300
jill
2
100
sam
sam
NULL
NULL
NULL
400
claire
3
200
jack
sam
jack
NULL
NULL
500
reed
3
300
jill
sam
jill
NULL
NULL
600
derrick
4
400
claire
sam
jack
claire
NULL
700
bill
4
500
reed
sam
jill
reed
NULL
You seem to be looking for a recursive query. One that keeps joining on the next level until there are no more levels to join to.
That can be used to get all of an employees managers, each manager as a new row.
You then want to pivot those rows in to columns. Note, however, that SQL is statically and strongly typed, which means that if you want a pivoted view, you have to choose in advance how many columns you're going to have.
For example...
WITH
recurse_upwards AS
(
SELECT
emp.emp_id,
emp.emp AS emp_name,
0 AS level,
mgr.emp_id AS manager_id,
mgr.emp AS manager_name,
mgr.manager_id AS next_manager_id
FROM
example AS emp
LEFT JOIN
example AS mgr
ON mgr.emp_id = emp.manager_id
UNION ALL
SELECT
emp.emp_id,
emp.emp_name,
emp.level + 1,
mgr.emp_id,
mgr.emp,
mgr.manager_id
FROM
recurse_upwards AS emp
INNER JOIN
example AS mgr
ON mgr.emp_id = emp.next_manager_id
)
SELECT
emp_id,
emp_name,
MAX(CASE WHEN level = 0 THEN manager_id END) AS manager_id,
MAX(CASE WHEN level = 0 THEN manager_name END) AS manager_name,
MAX(CASE WHEN level = 1 THEN manager_name END) AS manager_1_name,
MAX(CASE WHEN level = 2 THEN manager_name END) AS manager_2_name,
MAX(CASE WHEN level = 3 THEN manager_name END) AS manager_3_name,
MAX(CASE WHEN level = 4 THEN manager_name END) AS manager_4_name
FROM
recurse_upwards
GROUP BY
emp_id,
emp_name
ORDER BY
emp_id
Demo : https://dbfiddle.uk/Tj7rZ5bT

List the emps whose sal > his Manager but less than other Managers

List the emps whose sal > his Manager but salary less than other Managers
Table
emp_ID emp_Name emp_sal_K emp_manager
1 Ali 200 3
2 Zaid 620 4
3 Mohd 1140 2
4 LILY 600 NULL
5 John 1240 6
6 Mike 1160 4
7 John 1240 6
8 Mohd 1640 2
Query
select *
from emp_demo2 e1
where emp_sal_K >
(select emp_ID from emp_demo2 e2
where e1.emp_manager = e2.emp_ID and e2.emp_sal_K
< all
(select emp_id from emp_demo2 e3
where e2.emp_ID = e3.emp_id))
Result: null columns. There are 4 managers in total 2,4 ,6 and 3. Here clearly emp_id 2 Zaid is a person whose salary 620 is greater than his manager's salary emp_id 4 which is 600 but less than all other managers emp_id 6 and 3. So I should get that result but getting nothing.
Expected result
emp_ID emp_Name emp_sal_K emp_manager
2 Zaid 620 4
SELECT emp.*
FROM emp_demo2 emp
LEFT JOIN emp_demo2 mgr
ON emp.emp_manager = mgr.emp_id
WHERE emp.emp_sal_k > mgr.emp_sal_k
AND emp.emp_sal_k < (SELECT Min(mgr1.emp_sal_k)
FROM emp_demo2 emp1
JOIN emp_demo2 mgr1
ON emp1.emp_manager = mgr1.emp_id
WHERE mgr1.emp_id <> emp.emp_manager
AND mgr1.emp_id <> emp.emp_id)

Duplicating multiple records in table with primary key

I am working with duplicating multiple records in table 1 with primary key which has a reference with table 2 (foreign key)
Consider table employee with columns (eid(primary key),ename,dept,dept_code).
Table 2 employee_address with columns (eaid(primary key), eid(foreign key), city, country)
Now the task is the table 1 (ie. employee) may have number of values with different department codes.
Suppose dept_code may be 1 or 2 like so and so.
Now with both the table with some data look like this
EMPLOYEE table
Eid(pk) ename dept Dept_code
100 Sss Cse 1
101 Aaa Cse 1
102 Bbb Cse 1
103 Ccc Eee 2
104 ddd it 3
EMPLOYEE ADDRESS table
Eaid (pk) Eid (fk) city country
1 100 NY Us
2 100 NY Us
3 100 NY Us
4 101 CALIF Us
5 102 DC Us
6 102 DC Us
7 103 NJ Us
now the thing is i have to duplicate all the records in employee table where dept_code=1 and duplicate records dept_code should be = 5.
And the foreign key referencing to employee address table (ie. here in the current document 100,101,102) in the table 2 has to be duplicated number of times those foreign key value present in table 2.
I have to get the output like this
Employee table
Eid(pk) ename dept Dept_code
100 Sss Cse 1
101 Aaa Cse 1
102 Bbb Cse 1
103 Ccc Eee 2
104 ddd it 3
**105 sss cse 5
106 aaa cse 5
107 bbb cse 5**
Employee Address table
Eaid (pk) Eid (fk) city country
1 100 NY Us
2 100 NY Us
3 100 NY Us
4 101 CALIF Us
5 102 DC Us
6 102 DC Us
7 103 NJ Us
**8 105 NY Us
9 105 NY Us
10 105 Ny Us
11 106 CALIF Us
12 107 DC Us
13 107 DC Us**
Now I have to get the output like this.
Conditions for this task is,
no for loop
hitting a database should be as minimal as possible
can use java or if posssible in sql query itself.
I tried with various ideas nothing worked out.
Help me out in this.
If I understand your question, these two queries will work. They use tSql window functions, if you are not using Sql Server then you will need to find the equivalent.
Edited to answer comment from OP-
If you want to create new tables:
Select * Into EmployeeNew From (
Select *
From Employee E
Union All
Select Row_Number() Over (Order By eid) + (Select Max(eid) From Employee),
ename, dept, 5 dept_code
From Employee
Where Dept_Code = 1) A
Select * Into EmployeeAddressNew From (
Select A.*
From Employee E
Join EmployeeAddress A On A.eid = E.eid
Union All
Select A.eaid + (Select Max(eaid) From EmployeeAddress),
Dense_Rank() Over (Order By E.eid) + (Select Max(eid) From Employee),
City, Country
From Employee E
Join EmployeeAddress A On A.eid = E.eid
Where E.Dept_Code = 1) A
If you only want to insert 'new' records into the original tables:
Insert Employee
Select Row_Number() Over (Order By eid) + (Select Max(eid) From Employee),
ename, dept, 5 dept_code
From Employee
Where Dept_Code = 1
Insert EmployeeAddress
Select A.eaid + (Select Max(eaid) From EmployeeAddress),
Dense_Rank() Over (Order By E.eid) + (Select Max(eid) From Employee),
City, Country
From Employee E
Join EmployeeAddress A On A.eid = E.eid
Where E.Dept_Code = 1

Select from two tables without using an OR

I have two tables: employee and department
employee
name | salary | dNumber
A | 20000 | 1
B | 25000 | 1
C | 10000 | 5
D | 10000 | 1
department
departmentName | departmentNumber
math | 1
science | 2
How can I select from these two tables without using boolean operators like OR & AND?
I want to find the employee that works for department 1 or has a salary greater than $20,000.
What I tried:
select name from employee
where salary>= 20000 from (where dNumber in (select departmentNumber from department
where departmentNumber = 5));
That doesn't work because:
ERROR: syntax error at or near "where"
If the requirement is to not use an OR, you could use UNION instead. Since you filter the department on its number, not on its name, you do not need the second table at all:
SELECT name FROM employee WHERE salary > 20000
UNION
SELECT name FROM employee WHERE dNumber = 1
If you wanted to filter the department by name, a join or a subquery would be required:
SELECT name FROM employee WHERE salary > 20000
UNION
SELECT name FROM employee e
JOIN department d ON e.dNumber=d.departmentNumber
WHERE departmentName = 'math'
Here's how you do it:
select name from employee where where dnumber = 1
union
select name from employee where salary > 20000
Basically, union works like the OR operator and intersection works like the AND operator.

Select highest value over multiple tables

I have the following tables
Table Name : tHREmployee
EmployeID# Employee DepartmentID DesignationID DOB BasicPay
101 Ajith 101 102 10/Feb/1982 10000
102 Aarathy NULL 101 15/Mar/1981 15000
103 Aruna 102 NULL 20/Sep/1980 5000
104 Ambily 101 NULL 20/Sep/1980 5000
105 Anjaly NULL 101 20/Sep/1980 10000
106 Babitha 103 NULL 20/Sep/1981 20000
Table Name : tHRDepartment
DepartmentID# Code Department
101 500 Production
102 501 HR
103 502 Finance
105 503 Marketing
Table Name : tHRDesignation
DesignationID# Designation
101 Executive
102 Manager
How can I display employee details (Employee, Department, Designation, basicPay) for those employees who have highest basic pay for each department in sql?
In Oracle, this should help you
WITH CTE AS
(
SELECT DepartmentID , MAX(BasicPay) MAXPAY FROM tHREmployee
GROUP BY DepartmentID
)
SELECT E.EmployeID EMPid, E.Employee EMP_NAME , DPT.Department DPT_NAME,
DSG.Designation DSG_NAME, BASICPAY
FROM CTE, tHREmployee E,tHRDepartment DPT, Designation DSG
WHERE
E.BASICPAY = MAXPAY
AND E.DepartmentID = CTE.DepartmentID
AND E.DepartmentID = DPT.DepartmentID
AND E.DesignationID = DSG.DesignationID
In other DBs, something similar to this would help you:
SELECT E.EmployeID EMPid, E.Employee EMP_NAME , DPT.Department DPT_NAME,
DSG.Designation DSG_NAME, BASICPAY
FROM tHREmployee E,tHRDepartment DPT, Designation DSG
WHERE
E.DepartmentID = CTE.DepartmentID
AND E.DepartmentID = DPT.DepartmentID
AND E.DesignationID = DSG.DesignationID
AND E.BASICPAY IN
( SELECT MAX(EE.BASICPAY) FROM tHREmployee EE GROUP BY DPT.DepartmentID )
Select A.Employee,B.Department ,c.Designation,a.BAsicPay from Employee A inner join Department B on A.Department=B.DepartmentID left join Designation C on A.designationID=C.DesignationID inner join (Select DepartmentID,max(BasicPay) as BasicPay from Employee group by DepartmentID) as s2
on s2.DepartmentID=A.DepartmentID and A.BAsicPay=s2.BasicPAy