I have a table of salaries I want to find sum of all the salaries consecutively in a different column based on the manager_id. Suppose I have a table like this
Manager_id
Salary
100
1200
100
1400
100
1600
103
1800
104
1900
And I want output like this
Manager_id
Salary
Salary_Sum
100
1200
1200
100
1400
2600
100
1600
4200
103
1800
1800
104
1900
1900
SUM analytical function can fulfil your requirement but there must some other column also to order your rows apart from Manager_id -
SELECT
Manager_id,
Salary,
SUM(Salary) OVER(PARTITION BY Manager_id ORDER BY <other_column_for_ordering>) Salary_Sum
FROM salaries
ORDER BY Manager_id, <other_column_for_ordering>;
Related
Create PL / SQL blocks using cursors to update salary columns on employee tables, from employees working in specific departments inputted via keyboard.
Salaries are raised by the rules:
If the employee is less than 16 years old, raise the salary 15%
If the length of employment of employees between 16-20 years, increase salary by 20%
If the employee is over 20 years old, raise salary 25%
Show employee_id, last_name, old job, new salary, on updated employees table.
Enter value for d_id: 30
EMPLOYEE_ID LAST_NAME LAMAKERJA SALARY
----------- ------------------------- ---------- ----------
119 Colmenares 16.1452239 3000
118 Himuro 16.8794705 3120
116 Baida 17.7726212 3480
117 Tobias 18.1917992 3360
115 Khoo 20.3781006 3720
114 Raphaely 20.8219362 13200
6 rows selected.
To get you started: age is a common problem so let's suppose that my trivial calculation does the job. Loop through all employees, check conditions you were told and update employee's salary. The final SELECT is up to you, completely.
FOR cur_r
IN (SELECT employee_id, TRUNC ( (SYSDATE - date_of_birth) / 365.25) age
FROM employees)
LOOP
UPDATE employees e
SET e.salary =
e.salary * CASE
WHEN age ... THEN ...
WHEN age ... THEN ...
END
WHERE e.employee_id = ...
END LOOP;
I want to get both the child and one upper level parent information by using oracle connect by prior?
For example the folowing query retrieve child info and parent id,
SELECT last_name, employee_id, manager_id, LEVEL
FROM employees
START WITH employee_id = 100
CONNECT BY PRIOR employee_id = manager_id
but I want to get parent info also like
LAST_NAME EMPLOYEE_ID MANAGER_ID LEVEL MANAGER_NAME
------------------------- ----------- ---------- ----------------------------
King 100 1 ?
Cambrault 148 100 2 ?
Bates 172 148 3 ?
Bloom 169 148 3 .
Fox 170 148 3 .
How can I handle this problem, when I applied left join after selecting childs by connect by prior,The objects order is mixing.
You can refer to prior values in the select list:
SELECT last_name, employee_id, manager_id, LEVEL, prior last_name as manager_name
FROM employees
START WITH employee_id = 100
CONNECT BY PRIOR employee_id = manager_id;
LAST_NAME EMPLOYEE_ID MANAGER_ID LEVEL MANAGER_NAME
------------------------- ----------- ---------- ---------- -------------------------
King 100 1
Kochhar 101 100 2 King
Greenberg 108 101 3 Kochhar
Faviet 109 108 4 Greenberg
...
Cambrault 148 100 2 King
Bates 172 148 3 Cambrault
Bloom 169 148 3 Cambrault
Fox 170 148 3 Cambrault
...
I have a table employee which has hierarchy data of manager and employee.
Sample data.
empId ManId
101 100
102 100
1010 101
1011 101
10101 1010
I need to find the level but it is not giving me correct output. I need an output like
level Emp ID Man Id
1 101 100
1 102 100
2 1010 101
2 1011 101
3 10101 1010
Irrespective of the input as Emp ID or Man ID, the output should be constant. I am only getting the output when I am using manager id as 100 but it doesnt work when i pass value as 10101
select distinct
level,
manager_id,
employee_id
from employees
START WITH manager_id = 100
connect by manager_id= prior employee_id
order by level
START WITH clause is used to specify a root row for the hierarchy which is employee id with 101 value
Kindly use the below
select distinct
level,
manager_id,
employee_id
from employees
where level<=3
START WITH employee_id = 101
connect by manager_id= prior employee_id
order siblings by employee_id
Update1:-:-You can remove START WITH if root row is not specific
select distinct
level,
manager_id,
employee_id
from employees
where level<=3
connect by manager_id= prior employee_id
order siblings by employee_id
Check this link for more information
Hierarchical Queries
I have a table:
key product_code cost
1 UK 20
1 US 10
1 EU 5
2 UK 3
2 EU 6
I would like to find the sum of all products for each group of "key" and append to each row. For example for key = 1, find the sum of costs of all products (20+10+5=35) and then append result to all rows which correspond to the key = 1. So end result:
key product_code cost total_costs
1 UK 20 35
1 US 10 35
1 EU 5 35
2 UK 3 9
2 EU 6 9
I would prefer to do this without using a sub-join as this would be inefficient. My best idea would be to use the over function in conjunction with the sum function but I cant get it to work. My best try:
SELECT key, product_code, sum(costs) over(PARTITION BY key)
FROM test
GROUP BY key, product_code;
Iv had a look at the docs but there so cryptic I have no idea how to work out how to do it. Im using Hive v0.12.0, HDP v2.0.6, HortonWorks Hadoop distribution.
Similar to #VB_ answer, use the BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING statement.
The HiveQL query is therefore:
SELECT key, product_code,
SUM(costs) OVER (PARTITION BY key ORDER BY key ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
FROM test;
You could use BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW to achieve that without a self join.
Code as below:
SELECT a, SUM(b) OVER (PARTITION BY c ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
FROM T;
The analytics function sum gives cumulative sums. For example, if you did:
select key, product_code, cost, sum(cost) over (partition by key) as total_costs from test
then you would get:
key product_code cost total_costs
1 UK 20 20
1 US 10 30
1 EU 5 35
2 UK 3 3
2 EU 6 9
which, it seems, is not what you want.
Instead, you should use the aggregation function sum, combined with a self join to accomplish this:
select test.key, test.product_code, test.cost, agg.total_cost
from (
select key, sum(cost) as total_cost
from test
group by key
) agg
join test
on agg.key = test.key;
This query gives me perfect result
select key, product_code, cost, sum(cost) over (partition by key) as total_costs from zone;
similar answer (if we use oracle emp table):
select deptno, ename, sal, sum(sal) over(partition by deptno) from emp;
output will be like below:
deptno ename sal sum_window_0
10 MILLER 1300 8750
10 KING 5000 8750
10 CLARK 2450 8750
20 SCOTT 3000 10875
20 FORD 3000 10875
20 ADAMS 1100 10875
20 JONES 2975 10875
20 SMITH 800 10875
30 BLAKE 2850 9400
30 MARTIN 1250 9400
30 ALLEN 1600 9400
30 WARD 1250 9400
30 TURNER 1500 9400
30 JAMES 950 9400
The table above looked like
key product_code cost
1 UK 20
1 US 10
1 EU 5
2 UK 3
2 EU 6
The user wanted a tabel with the total costs like the following
key product_code cost total_costs
1 UK 20 35
1 US 10 35
1 EU 5 35
2 UK 3 9
2 EU 6 9
Therefor we used the following query
SELECT key, product_code,
SUM(costs) OVER (PARTITION BY key ORDER BY key ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
FROM test;
So far so good.
I want a column more, counting the occurences of each country
key product_code cost total_costs occurences
1 UK 20 35 2
1 US 10 35 1
1 EU 5 35 2
2 UK 3 9 2
2 EU 6 9 2
Therefor I used the following query
SELECT key, product_code,
SUM(costs) OVER (PARTITION BY key ORDER BY key ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as total_costs
COUNT(product code) OVER (PARTITION BY key ORDER BY key ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as occurences
FROM test;
Sadly this is not working. I get an cryptic error. To exclude an error in my query I want to ask if I did something wrong.
Thanks
I want to display manager_name and count of employees reporting him in employees table.I want to sort the data based on count IE maximum employees reporting to a manager should come first.
I tried to write self join but i could not get the out put .
EMPLOYEE_ID FIRST_NAME MANAGER_ID SALARY HIRE_DATE
198 Donald 124 2600 21-JUN-99
199 Douglas 124 2600 13-JAN-00
200 Jennifer 101 4400 17-SEP-87
201 Michael 100 13000 17-FEB-96
202 Pat 201 6000 17-AUG-97
203 Susan 101 6500 07-JUN-94
204 Hermann 101 10000 07-JUN-94
205 Shelley 101 12000 07-JUN-94
206 William 205 8300 07-JUN-94
100 Steven 24000 17-JUN-87
101 Neena 100 17000 21-SEP-89
the table name is employees and i want to see names also
You can use the aggregate function COUNT and ORDER BY clause
You didn't mention the table name assuming the table name as EMPLOYEES, below query would help you.
SELECT MANAGER_ID, COUNT(EMPLOYEE_ID) as EMP_COUNT
FROM EMPLOYEES
GROUP BY MANAGER_ID
ORDER BY EMP_COUNT DESC;
Here EMP_COUNT is the column alias name.If you don't want any column alias you can simply use the query below.
SELECT MANAGER_ID, COUNT(EMPLOYEE_ID)
FROM EMPLOYEES
GROUP BY MANAGER_ID
ORDER BY COUNT(EMPLOYEE_ID) DESC;
If you want to sort by ascending order instead of DESC you can use ASC.
We can get this output using an analytical function:
SELECT E.EMPID,E.EMPNAME as "Manager Name",M.EMPNAME AS "Employee Name",count(*) over(partition by e.empid) reportee_count
from empmgid m,empmgid e where M.MAGID=e.EMPID order by reportee_count desc;
Please employ the following SQL-Query:
SELECT
e.empno,
e.ename,
e1.empcnt
FROM
emp e,
(
SELECT
mgr,
COUNT(*) empcnt
FROM
emp
GROUP BY
mgr
) e1
WHERE
e.empno = e1.mgr;
-- Restricting which manager is having two employees working under them
-----------------------------------------------------------------------
SELECT E1.* FROM
(
SELECT E1.EMPNO,E1.ENAME AS EMPLOYE,
M1.ENAME AS MANAGERS,
COUNT(*)
OVER
(
PARTITION BY E1.EMPNO
) EMPCNT
FROM EMP E1,EMP M1
WHERE M1.MGR=E1.EMPNO
) E1
WHERE EMPCNT = 2;
select count(distinct manager_id) from employees;
select count(distinct manager_id) from employees;
Ans:
COUNT(DISTINCTMANAGER_ID)
18