avg sql function [closed] - sql

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
I have a table employees
EMPLOYEE_ID FIRST_NAME LAST_NAME HIRE_DATE JOB_ID SALARY DEPARTMENT_ID
-------------------------------------------------------------------------------------------
100 Steven King 17-JUN-03 AD_PRES 24000 90
101 Neena Kochhar 21-SEP-05 AD_VP 17000 90
102 Lex De Haan 13-JAN-01 AD_VP 17000 90
103 Alexander Hunold 03-JAN-06 IT_PROG 9000 60
104 Bruce Ernst 21-MAY-07 IT_PROG 6000 60
105 David Austin 25-JUN-05 IT_PROG 4800 60
106 Valli Pataballa 05-FEB-06 IT_PROG 4800 60
107 Diana Lorentz 07-FEB-07 IT_PROG 4200 60
109 Daniel Faviet 16-AUG-02 FI_ACCOUNT 9000 100
110 John Chen 28-SEP-05 FI_ACCOUNT 8200 100
111 Ismael Sciarra 30-SEP-05 FI_ACCOUNT 7700 100
112 Jose Manuel Urman 07-MAR-06 FI_ACCOUNT 7800 100
113 Luis Popp 07-DEC-07 FI_ACCOUNT 6900 100
and table departments
DEPARTMENT_ID DEPARTMENT_NAME
-------------------------------
30 Purchasing
50 Shipping
60 IT
90 Executive
100 Finance
I need to write 3 queries:
Get department name and number of employees in each department sorting ascending
I tried this
select count(e.employee_id), d.department_name
from t_employees e, t_departments d
where d.department_id = e.department_id
group by e.department_name
order by count(e.employee_id);
Not sure if it will work since I can not really try it.
Get department name and average salary where average salary by department is more or equal 5000
Result table
DEPARTMENT_NAME AVERAGE_SALARY
---------------------------------
Executive 19333,333
IT 5760
Finance 7920`
select d.department_name, AVG(e.salary) as AVARAGE_SALARY
from t_departments d, t_employees e
where d.department_id = e.department_id
and avg(e.salary) >= '5000'
group by d.department_name;
Get first name and last name of employees who have salary bigger than the average salary from the department they work in
Result table
FIRST_NAME LAST_NAME
---------------------------------
Steven King
Alexander Hunold
Bruce Ernst
Daniel Faviet
John Chen
I have no code for this one.

You're quite close.
I don't have your tables so I'll use Scott's sample schema. Try to apply it to your data model.
First:
SQL> select d.dname, count(*) cnt
2 from emp e join dept d on e.deptno = d.deptno
3 group by d.dname
4 order by cnt desc;
DNAME CNT
-------------- ----------
SALES 6
RESEARCH 5
ACCOUNTING 3
Second: not where, but having:
SQL> select d.dname, avg(e.sal) avg_sal
2 from emp e join dept d on e.deptno = d.deptno
3 group by d.dname
4 having avg(e.sal) > 2000; --> this
DNAME AVG_SAL
-------------- ----------
ACCOUNTING 2916,66667
RESEARCH 2175
SQL>
Third:
SQL> with avgsal as
2 (select deptno,
3 round(avg(sal), 1) avgsal
4 from emp
5 group by deptno
6 )
7 select e.deptno, e.ename, e.sal, a.avgsal
8 from emp e join avgsal a on a.deptno = e.deptno
9 where e.sal > a.avgsal
10 order by e.deptno;
DEPTNO ENAME SAL AVGSAL
---------- ---------- ---------- ----------
10 KING 5000 2916,7
20 JONES 2975 2175
20 SCOTT 3000 2175
20 FORD 3000 2175
30 ALLEN 1600 1566,7
30 BLAKE 2850 1566,7
6 rows selected.
SQL>

Related

How to select middle 80% rows in Oracle SQL with order by (top % is not working)

I tried top % but that is not working in Oracle SQL. Offset and fetch next are working but I am not able to give percentage.
What will be the best way to fetch middle 80% rows?
Any help will be appreciated, thanks!
Middle 80%? That's between 10 and 90%, then? Let's suppose it is.
Sample data (Scott's EMP table), sorted by salary:
SQL> select ename, job, sal,
2 rank() over (order by sal) rnk
3 from emp order by sal;
ENAME JOB SAL RNK
---------- --------- ---------- ----------
SMITH CLERK 800 1
JAMES CLERK 950 2
ADAMS CLERK 1100 3
WARD SALESMAN 1250 4
MARTIN SALESMAN 1250 4
MILLER CLERK 1300 6
TURNER SALESMAN 1500 7
ALLEN SALESMAN 1600 8
CLARK MANAGER 2450 9
BLAKE MANAGER 2850 10
JONES MANAGER 2975 11
SCOTT ANALYST 3000 12
FORD ANALYST 3000 12
KING PRESIDENT 5000 14
14 rows selected.
CTE ranks employees by their salaries; the final where clause returns rows for those of them who fall into that "middle" 80% (the pct column).
SQL> with temp as
2 (select ename, job, sal,
3 rank() over (order by sal) rnk, -- rank rows by salary
4 count(*) over (order by null) cnt -- total number of rows
5 from emp
6 )
7 select t.*,
8 round(rnk / cnt * 100) pct -- percentage
9 from temp t
10 where round(rnk / cnt * 100) between 10 and 90;
ENAME JOB SAL RNK CNT PCT
---------- --------- ---------- ---------- ---------- ----------
JAMES CLERK 950 2 14 14
ADAMS CLERK 1100 3 14 21
WARD SALESMAN 1250 4 14 29
MARTIN SALESMAN 1250 4 14 29
MILLER CLERK 1300 6 14 43
TURNER SALESMAN 1500 7 14 50
ALLEN SALESMAN 1600 8 14 57
CLARK MANAGER 2450 9 14 64
BLAKE MANAGER 2850 10 14 71
JONES MANAGER 2975 11 14 79
SCOTT ANALYST 3000 12 14 86
FORD ANALYST 3000 12 14 86
12 rows selected.
SQL>

SQL Grouping of Salaries

I have a question to ask and I am supposed to create a query which shows:
MIN(lastname) MAX(firstname) SUM(salary) AVG(salary)
---------------------------------------------------------------
DAVIES TRINA 17500 3500
This was the query/queries I created:
SQL> SELECT MIN(LASTNAME), MAX(FIRSTNAME), SUM(SALARY), AVG(SALARY)
2 FROM EMPLOYEES
3 GROUP BY JOB_ID;
SQL> SELECT MIN(LASTNAME), MAX(FIRSTNAME), SUM(SALARY), AVG(SALARY)
2 FROM EMPLOYEES
3 GROUP BY JOB_ID, MANAGER_ID;
But I get multiple rows shown to me and in the part where DAVIES TRINA was shown the SUM and AVG salary is different and I am unsure how they were grouped.
MIN(LASTNAME) MAX(FIRSTNAME) SUM(SALARY) AVG(SALARY)
---------- ---------- ----------- -----------
ERNST DIANA 10200 5100
HIGGINS SHELLEY 12000 12000
GIETZ WILLIAM 8300 8300
MOURGOS KEVIN 5800 5800
WHALEN JENNIFER 4400 4400
DE HAAN NENA 34000 17000
ZLOTKEY ELENI 10500 10500
HARTSTEIN MICHAEL 13000 13000
KING STEVEN 24000 24000
ABEL KIMBERLEY 26600 8866.66667
FAY PAT 6000 6000
**DAVIES TRINA 11700 2925**
What am I doing wrong?
MORE INFO BELOW:
EMPLOYEE_ID FIRSTNAME LASTNAME JOB_ID SALARY MANAGER_ID DEPARTMENT_ID
100 STEVEN KING AD_PRES 24000 90
101 NENA KOCHAR AD_VP 17000 100 90
102 LEX DE HAAN AD_VP 17000 100 90
103 ALEXANDER HUNOLD IT_PROG 101 60
104 BRUCE ERNST IT_PROG 6000 102 60
107 DIANA LORENTZ IT_PROG 4200 103 60
124 KEVIN MOURGOS ST_MAN 5800 100 50
141 TRINA RAJS ST_CLERK 3500 124 50
142 CURTIS DAVIES ST_CLERK 3100 124 50
143 RANDALL MATOS ST_CLERK 2600 124 50
144 PETER VARGAS ST_CLERK 2500 124 50
EMPLOYEE_ID FIRSTNAME LASTNAME JOB_ID SALARY MANAGER_ID DEPARTMENT_ID
149 ELENI ZLOTKEY SA_MAN 10500 100 80
174 ELLEN ABEL SA_REP 11000 149 50
176 JONATHAN TAYLOR SA_REP 8600 149 80
178 KIMBERLEY GRANT SA_REP 7000 149
200 JENNIFER WHALEN AD_ASST 4400 101 10
201 MICHAEL HARTSTEIN MK_MAN 13000 100 20
202 PAT FAY MK_REP 6000 201 20
205 SHELLEY HIGGINS AC_MGR 12000 101 110
206 WILLIAM GIETZ AC_ACCOUNT 8300 205 110
If you provide the proper data that is, the data before running the query/queries and also tell why it should be 17500(sum) and 3500(avg) then you have more chances to get answers.
In the 1st query you are grouping based on JOB_ID. That means for all similar JOB_IDs (in case of SUM(SALARY)) it will select the the values of SALARY column and SUM the values for each different JOB_ID.
Example:
JOB_ID SALARY
1 200
2 300
1 150
2 100
3 270
If you run the following query:
Select JOB_ID,SUM(SALARY) FROM Table GROUP BY JOB_ID
Output:
JOB_ID SALARY
1 350
2 400
3 270

How to display department (once) and list of all employees working in that department?

For the schema epartments(department_id, department_name) employees(last_name, department_id, salary)
I want to display the department_id, department_name, count(employees),avg(salary),last_name,salary
I have tried using the following query
SELECT d1.department_id,d1.department_name,d1."count",d1."avg",e.last_name,e.salary
FROM employees e
INNER JOIN (SELECT d.department_id,d.department_name,count(e.last_name) AS "count",round(avg(e.salary),2) AS "avg"
FROM employees e,departments d
WHERE e.department_id=d.department_id
GROUP BY d.department_id,d.department_name) d1
ON e.department_id=d1.department_id;
While it displays the correct output it is not in the format I want.
The above query gives output as
90 Executive 3 19333.33 King 24000
90 Executive 3 19333.33 Kochhar 17000
90 Executive 3 19333.33 De Haan 17000
60 IT 3 6400 Hunold 9000
60 IT 3 6400 Ernst 6000
60 IT 3 6400 Lorentz 4200
50 Shipping 5 3500 Mourgos 5800
While it should be like
90 Executive 3 19333.33 King 24000
Kochhar 17000
De Haan 17000
60 IT 3 6400 Hunold 9000
Ernst 6000
Lorentz 4200
50 Shipping 5 3500 Mourgos 5800
If you really want to show something like '' instead of those data in your query, I think you can use ROW_NUMBER() for that like this:
CASE
WHEN (ROW_NUMBER() OVER (PARTITION BY d1.department_id
ORDER BY d1.department_id)) = 1 THEN
d1.department_id
ELSE
Null
END
for columns: d1.department_id,d1.department_name,d1."count",d1."avg".

Query to sum the previous values

I have the table strucure as in the image.
I need to get the values added to the sum of previous values(shown in the REQUIRED RESULT)
I tried with the following query
SELECT empid,
sum(tot_hours) OVER (PARTITION BY empid ORDER BY empid ) AS tot_hours
FROM empDet
ORDER BY empid
But i get the following result set
But I need the result as in the first picture.
Can anyone help me doing this?
sum(tot_hours) OVER (PARTITION BY empid ORDER BY empid ) AS tot_hours
Your ORDER BY is incorrect. If you want the running SUM on the TOT_HOURS, then you should order by tot_hours.
For example, the below query will calculate the running sum of salary of employees in each department:
SQL> SELECT deptno,
2 sal,
3 SUM(sal) OVER (PARTITION BY deptno ORDER BY sal ) AS tot_sal
4 FROM emp
5 ORDER BY deptno;
DEPTNO SAL TOT_SAL
---------- ---------- ----------
10 1300 1300
10 2450 3750
10 5000 8750
20 800 800
20 1100 1900
20 2975 4875
20 3000 10875
20 3000 10875
30 950 950
30 1250 3450
30 1250 3450
30 1500 4950
30 1600 6550
30 2850 9400
14 rows selected.
SQL>
Update For duplicate values, the running total would be duplicate. To make it unique, use UNBOUNDED PRECEDING clause. For example,
SQL> SELECT empno, deptno,
2 sal,
3 SUM(sal) OVER (PARTITION BY deptno ORDER BY sal ROWS UNBOUNDED PRECEDING) AS tot_sal
4 FROM emp
5 ORDER BY deptno;
EMPNO DEPTNO SAL TOT_SAL
---------- ---------- ---------- ----------
7934 10 1300 1300
10 1300 2600
7782 10 2450 5050
7839 10 5000 10050
7369 20 800 800
7876 20 1100 1900
7566 20 2975 4875
7788 20 3000 7875
7902 20 3000 10875
7900 30 950 950
7521 30 1250 2200
7654 30 1250 3450
7844 30 1500 4950
7499 30 1600 6550
7698 30 2850 9400
15 rows selected.
SQL>

A problem with getting the correct data

I have created a query that looks like this but I havent found a way to group the departments together. Thats the part I need help with. I want to get Department number in one colum, Employee is another and then the person that would be their colleague in another. Any help would be great.
This is what I want it to look like
DEPARTMENT EMPLOYEE COLLEAGUE
10 CLARK KING
10 CLARK MILLER
10 KING CLARK
10 KING MILLER
10 MILLER CLARK
10 MILLER KING
20 ADAMS FORD
20 ADAMS JONES
20 ADAMS SCOTT
20 ADAMS SMITH
And here is what I got so far but is not correct.Kings colleague is not King its Clark and Miller. Clarks colleague is not Clark its king and Miller.
SQL> select ename AS Employee, deptno AS Department, ename AS Colleague from emp order by deptno asc;
EMPLOYEE DEPARTMENT COLLEAGUE
---------- ---------- ----------
KING 10 KING
CLARK 10 CLARK
MILLER 10 MILLER
ADAMS 20 ADAMS
SCOTT 20 SCOTT
SMITH 20 SMITH
FORD 20 FORD
JONES 20 JONES
WARD 30 WARD
JAMES 30 JAMES
ALLEN 30 ALLEN
EMPLOYEE DEPARTMENT COLLEAGUE
---------- ---------- ----------
MARTIN 30 MARTIN
BLAKE 30 BLAKE
TURNER 30 TURNER
14 rows selected.
Heres the dept table
SQL> select * from dept;
DEPTNO DNAME LOC
---------- -------------- -------------
10 ACCOUNTING NEW YORK
20 RESEARCH DALLAS
30 SALES CHICAGO
40 OPERATIONS BOSTON
Heres the emp table
SQL> select ename, deptno, job from emp;
ENAME DEPTNO JOB
---------- ---------- ---------
KING 10 PRESIDENT
BLAKE 30 MANAGER
CLARK 10 MANAGER
JONES 20 MANAGER
MARTIN 30 SALESMAN
ALLEN 30 SALESMAN
TURNER 30 SALESMAN
JAMES 30 CLERK
WARD 30 SALESMAN
FORD 20 ANALYST
SMITH 20 CLERK
ENAME DEPTNO JOB
---------- ---------- ---------
SCOTT 20 ANALYST
ADAMS 20 CLERK
MILLER 10 CLERK
14 rows selected.
It sounds like you want something like
SQL> ed
Wrote file afiedt.buf
1 select deptno department,
2 e1.ename employee,
3 e2.ename colleague
4 from emp e1 join emp e2 using (deptno)
5 where e1.empno != e2.empno
6* order by deptno
SQL> /
DEPARTMENT EMPLOYEE COLLEAGUE
---------- ---------- ----------
10 MILLER CLARK
10 KING CLARK
10 MILLER KING
10 CLARK MILLER
10 KING MILLER
10 CLARK KING
<<additional results removed>>
Select distinct d.dname, t1.employee, t2.employee college
From emp t1
inner join dept d on d.deptno = t1.deptno
Inner join emp t2 on t2.deptno = t1.deptno and t1.employee <> t2.employee