Cube SQL ORA-00936 missing expression - sql

im trying using cube in my query but it didnt work
this is my query
select department_id, job_id , salary/12 as "monthly_salary"
from employees
where department_id
(select department_id from departments)
group by cube(department_id,job_id)
order by department_id,job_id;
by using 2 tables which is employees and departments
forgive me if im asking too much,im still new to this :)

Not entirely sure what you are asking, but here is an example of a cube to get totals by deptno, job and the combination of the two
SQL> select deptno,job,sum(sal) from scott.emp
2 group by CUBE(deptno,job)
3 order by deptno,job;
DEPTNO JOB SUM(SAL)
---------- --------- ----------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
10 8750
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
20 10875
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
30 9400
ANALYST 6000
CLERK 4150
MANAGER 8275
PRESIDENT 5000
SALESMAN 5600
29025

You're missing
IN keyword (for list of departments)
SUM function for salaries
I included ROUND so that it looks prettier
So:
SELECT department_id,
job_id,
ROUND (SUM (salary) / 12) monthly_salary
FROM employees
WHERE department_id IN (SELECT department_id FROM departments)
GROUP BY CUBE (department_id, job_id)
ORDER BY department_id, job_id

Related

How do I find the salary of different job positions in the same department?

Using oracle's HR Database I want to find the salaries (just a sum of all the salaries) of every job position in a department, the result should be something like this
I have absolutely no idea about what to do here.
I don't have HR schema so here's how it would look like in Scott's. Adjust it to your data model.
Join departments to employees (so that you could fetch department name), get the job and compute sum of all salaries. Columns that aren't aggregated have to be part of the group by clause.
SQL> select d.dname, e.job, sum(e.sal)
2 from dept d join emp e on e.deptno = d.deptno
3 group by d.dname, e.job
4 order by d.dname, e.job;
DNAME JOB SUM(E.SAL)
-------------- --------- ----------
ACCOUNTING CLERK 1300.1
ACCOUNTING MANAGER 2450
ACCOUNTING PRESIDENT 5000
RESEARCH ANALYST 6000
RESEARCH CLERK 1900.2
RESEARCH MANAGER 2975
SALES CLERK 950.1
SALES MANAGER 2850
SALES SALESMAN 5600.4
9 rows selected.
SQL>

What is the best way(in case of performance) to find out the user details with maximum salary?

We have user details with a column of salary also, how can we print the user details with the maximum salary, I don't want to use the Subquery, and yeah how subquery will reduce the performance.
I know this query is wrong but I want something like this:
select User_name, user_id
from dual where salary=Max(salary);
Analytic functions help.
Using a CTE (which is kind of a subquery; don't be afraid of it, it doesn't bite and won't affect performance), query might look like this (based on sample Scott's schema):
SQL> select ename, sal from emp order by sal desc;
ENAME SAL
---------- ----------
KING 5000 --> this is the highest salary
FORD 3000 --> FORD and SCOTT share the 2nd place
SCOTT 3000
JONES 2975
BLAKE 2850
CLARK 2450
ALLEN 1600
TURNER 1500
MILLER 1300
WARD 1250 --> WARD and MARTIN are then 9th
MARTIN 1250
ADAMS 1100
JAMES 950
SMITH 800
14 rows selected.
Query is then
SQL> with temp as
2 (select ename,
3 dense_rank() over (order by sal desc) rnk
4 from emp
5 )
6 select ename
7 from temp
8 where rnk = 1;
ENAME
----------
KING
SQL>
Why dense_rank? Because two (or more) employees can have the same salary so they "rank" the same. For example, if you want to know whose salary is ranked as 9th, you'd
SQL> l8
8* where rnk = 1
SQL> c/1/9
8* where rnk = 9
SQL> /
ENAME
----------
WARD
MARTIN
SQL>
Query you suggested (although wrong, but - I got the idea) looks like this:
SQL> select ename
2 from emp
3 where sal = (select max(sal) from emp);
ENAME
----------
KING
SQL>
And yes, it affects performance because you're fetching data from the same emp table twice: once to find the max salary (in a subquery), and then in the main query to find who it belongs to.

About "group function is not allowed here"

I have a table with job, salary and date columns. I am writing the following query in PL/SQL, but I am getting an error
group function is not allowed here
delete employees where date = '06-05-2020 'and avg (salary)> 5500;
How can I solve this problem?
Your query makes no sense (to me, at least). What does that average salary represent? Whose average salary?
Here's an example based on Scott's EMP table; I'm going to delete employees who were hired on 3th of December 1981 and work in department whose employees' average salary is higher than 2000.
Sample data:
SQL> select deptno, ename, sal, hiredate from emp order by deptno, ename;
DEPTNO ENAME SAL HIREDATE
---------- ---------- ---------- ----------
20 ADAMS 1100 12.01.1983
20 FORD 3000 03.12.1981 --> this
20 JONES 2975 02.04.1981
20 SCOTT 3000 09.12.1982
20 SMITH 800 17.12.1980
30 ALLEN 1600 20.02.1981
30 BLAKE 2850 01.05.1981
30 JAMES 950 03.12.1981 --> this
30 MARTIN 1250 28.09.1981
30 TURNER 1500 08.09.1981
30 WARD 1250 22.02.1981
11 rows selected.
Averege salaries per department:
SQL> select deptno, avg(sal) avg_salary
2 from emp
3 group by deptno
4 order by avg_salary desc;
DEPTNO AVG_SALARY
---------- ----------
20 2175 --> higher than 2000
30 1566,66667
So: I'm looking for employees who work in department 20 (as only that department has average salaries higher than 2000) and who were hired on 03.12.1981 (James and Ford, but only Ford works in department 20):
SQL> delete from emp
2 where hiredate = date '1981-12-03'
3 and deptno in (select deptno
4 from emp
5 group by deptno
6 having avg(sal) > 2000
7 );
1 row deleted.
Is Ford still in there?
SQL> select * From emp where ename = 'FORD';
no rows selected
SQL>
Nope, deleted.
Now, your turn.

SQL how to order on highest rank in group, with total group

dataset taken from: Tim Hall's Oracle-Base rank/partition documentation Original assignment was to rank the salaries within a department. The MYRANK column is syntactic and introduced with
RANK() OVER (PARTITION BY deptno ORDER BY sal) AS myrank
But now I want to sort on the highest salary followed with all records within the same department. Then the second highest salary again followed with all the records in the same department. The order of dept is a kind of coincidental, it happens to be aligned with the order of highest salary per departnement.
I think I can solve this when the rank() is substituted for a max() like:
MAX() OVER (PARTITION BY DEPTNO ORDER BY SAL) AS MAX
and than a order by MAX, DEPTNO, but this fails with: invalid number of arguments
EMPNO DEPTNO SAL MYRANK
---------- ---------- ---------- ----------
7839 10 5000 3
7782 10 2450 2
7934 10 1300 1
7788 20 3000 4
7902 20 3000 4
7566 20 2975 3
7876 20 1100 2
7369 20 800 1
7698 30 2850 6
7499 30 1600 5
7844 30 1500 4
7654 30 1250 2
7521 30 1250 2
7900 30 950 1
You can put analytic functions in the order by, so you can do:
order by max(sal) over (partition by deptno) desc,
deptno,
sal desc
Notice that this has three keys in the order by. The deptno is needed in case two departments have the same highest salary.

About sql subquery

What to do when we want to select salary of a employee greater than many (lets say 12) employees's salary from a table. I know that we'll have to use a subquery but writing it as :-
Select ename,salary
from emp
where salary>( select salary
from emp
where ename='A'||ename='B'.....)
it could be written like that but its not a good approach. Please suggest some useful query for it.
If you know the 12 employees, I think you want to write the query as:
Select ename,salary
from emp
where salary> (select max(salary)
from emp
where ename in ('A', 'B', . . . )
)
IN is much more convenient than a bunch of or statements. And, the subquery needs to return one value, the maximum salary.
Select ename,salary
from emp
where salary > (
select salary
from
(
select
salary,
rownum as rn
from emp
order by salary
)
where rn = 12
)
This is not exact code that you may use, but it should help you.
You can use RANK() function.
Example from article at oracle-base.com:
SELECT empno,
deptno,
sal,
RANK() OVER (PARTITION BY deptno ORDER BY sal) "rank"
FROM emp;
EMPNO DEPTNO SAL rank
---------- ---------- ---------- ----------
7934 10 1300 1
7782 10 2450 2
7839 10 5000 3
7369 20 800 1
7876 20 1100 2
7566 20 2975 3
7788 20 3000 4
7902 20 3000 4
7900 30 950 1
7654 30 1250 2
7521 30 1250 2
7844 30 1500 4
7499 30 1600 5
7698 30 2850 6
I can see two different interpretations of your requirement.
1. What employees earn more than 12 other (random) employees
and
2. What employees earn more than 12 specific employees
This query solves the first requirement, although it will become slow as hell on larger datasets.
select *
from emp a
where 12 = (select count(*)
from emp b
where b.salary < a.salary);
This query solves the second requirement
select *
from emp
where salary > all(select salary
from emp
where emp_id in(1,2,3,4,5)
)