SQL - Partition by - from Oracle to SQL server - sql

I have two tables as below:
create table emp
( empno NUMBER(4) constraint E_PK primary key
, job VARCHAR2(8)
, deptno NUMBER(2) default 10
) ;
create table departments
( deptno NUMBER(2) constraint D_PK primary key
, dname VARCHAR2(10)
) ;
In Oracle, I have a query to show all employee with these position title of each department
select d.dname as department
, e.job as job
, e.ename as emp
from emp e
PARTITION BY (JOB)
right outer join
departments d
using (deptno)
order by department, job;
And the result:
DEPARTMENT JOB EMP
---------- -------- --------
ACCOUNTING Designer Chris
Peter
Manager Mike
Tester null
TRAINER null
HR Designer
Manager
Tester
TRAINER
SALES Designer Black
Manager Jane
Tester Mary
Jack
Wil
Take
TRAINER null
TRAINING Designer Jane
Manager null
Tester null
TRAINER Fake
Smart
Tom
Ana
Can I convert this query to SQL Server (2012 version)
Thanks

You can join the 2 tables to get data. The difference will be that Department will be populated in each row.
SELECT
d.dname AS Department
,e.Job
,e.ename AS Emp
FROM
departments d
LEFT OUTER JOIN emp e ON d.deptno = e.deptno
ORDER BY
d.dname
,e.Job
,2.ename
To get around this, you will have to tweak a bit:
SELECT
CASE WHEN RowNo = 1 THEN Department ELSE '' END AS Department
,Job
,Emp
FROM
(SELECT
d.dname AS Department
,e.Job
,e.ename AS Emp
,ROW_NUMBER() OVER (Partition By d.deptno ORDER BY e.Job,e.ename) RowNo
FROM
departments d
LEFT OUTER JOIN emp e ON d.deptno = e.deptno
) Result
ORDER BY
Result.RowNo

Related

How to display deptno, deptname and no of employee?

I am practicing my SQL skills with "EMP" and "Dept" table given in Oracle 11g
I am trying to display department no , department name and no of employees of the department where employee no is greater than 4?
You can group by the department's details and apply a having condition:
SELECT d.deptno, d.deptname, COUNT(*)
FROM dept d
JOIN emp e ON d.deptno = e.deptno
GROUP BY d.deptno, d.deptname
HAVING COUNT(*) > 4

How to count the number of members of different departments after executing a JOIN between two tables?

I have a table Emp and another table Dept
This is table Emp
This is table Dept
The query I have to execute is to display the average salary (i.e., sal) for all departments (i.e. DeptName) with more than 5 working people. So we'll have to do a JOIN or something and match the DeptID here with the DeptID there etc.
This is really confusing and I don't understand how to go about it.
you can use group by with having clause query for that.
group by Dept_id and check count using having clause.
SELECT
SUM(E.Sal) / COUNT(E.Dept_id) AS Avg_Sal,
E.Dept_Id
FROM EMP E
JOIN Dept D
ON D.DeptId = E.Dept_Id
GROUP BY E.DeptId
HAVING COUNT(E.Dept_Id) > 5
Select
DeptName,
AVG(sal) as averageSalary,
Count(EmpId) as NumberofEE
FROM Emp e
/*Left Join Because there are Nulls in the Dept_Id each Emp should belong to
1 dept*/
LEFT JOIN Dept d on e.Dept_Id = d.DeptId
GROUP BY
DeptName
Having Count(EmpId)> 5
This will give you the average salary (i.e., sal) for all departments (i.e. DeptName) with more than 5 working people
If i'm right with your requirement.

small tricky query on self join

I have a table EMP with columns as below:
create table emp(
empno number(4,0),
ename varchar2(10),
job varchar2(9),
mgr_id number(4,0),
sal number(7,2),
deptno number(2,0));
I want to list all employees' names along with their manager names, including those who do not have a manager. For those employees, their manager's name should be displayed as 'BOSS'.
The following query should work:
select e.ename, (case when m.ename is null then 'BOSS' else m.ename end) as mgrName
from emp e
left join emp m on m.empno = e.mgr_id
To my mind, the better solution is proposed by Charanjith.
In Oracle, we could even use NVL function instead of "case when" in order to replace null value by something. The result should be the same.
select e.ename empName, NVL(m.ename, 'BOSS') mgrName from emp e
left join emp m on m.empno = e.mgr_id
Moreover, we could see another solution : using inner join to filter on emp when a manager exists. Then union for all employees who don't have any manager.
select e.ename empName, m.ename mgrName from emp e inner join emp m on e.mgr_id = m.empno
union
select e.ename empName, 'BOSS' mgrName from emp e where not exists (select 1 from emp m where e.mgr_id = m.empno)
This work fine in oracle:
SELECT e.ename,
nvl(m.ename, 'BOSS')mgr
FROM emp a
LEFT JOIN emp b
ON m.empno = e.mgr_id;

Select departments with or without employees. Also select employees if assigned

I want to select DNAME, DEPTNO from all departments with or without employees assigned. And if a department does have any employees I want to get their ENAME, EMPNO.
I tried this: select e.empno,e.name,d.deptno,d.dname from emp e full join dept d
on e.deptno=d.deptno
But it didn't work.
Table structure:
DEPT
DEPTNO DNAME
EMP
EMPNO ENAME DEPTNO
Use OUTER JOIN(LEFT/RIGHT)
SELECT D.DEPTNO,
D.DNAME,
E.EMPNO,
E.ENAME
FROM DEPT D
LEFT OUTER JOIN EMP E
ON D.DEPTNO = E.DEPTNO
When the Department does not have any employee then NULL will be displayed in E.EMPNO and E.ENAME column
SELECT
DEPT.DEPTNO,DEPT.DNAME,EMP.EMPNO,EMP.NAME
FROM
DEPT LEFT OUTER JOIN
EMP ON DEPT.DEPTNO = EMP.DEPTNO

how to navigate in self loop tables?

Consider the following table
create table EMPLOYEE
(
empno NUMBER not null,
ename VARCHAR2(100),
salary NUMBER,
hiredate DATE,
manager NUMBER
);
alter table EMPLOYEE add constraint PK_EMP primary key (EMPNO);
alter table EMPLOYEE
add constraint FK_MGR foreign key (MANAGER)
references EMPLOYEE (EMPNO);
which is a self looped table i.e. every employee has a manager, except for the root.
I want to run the following query on this table:
find all the employees having more salary than their managers?
P.S.
There is only one root in the structure
consider the following query
SELECT LPAD(emp.ename, (LEVEL-1)*5 + LENGTH(emp.ename), ' ') AS "Hierarchy"
FROM employee emp
START WITH emp.manager IS NULL
CONNECT BY manager = PRIOR empno;
the result would be something like this:
Alice
Alex
Abbey
Sarah
Jack
Bill
Jacob
Valencia
Bob
Babak
...
I made the following query
SELECT LPAD(emp.ename, (LEVEL-1)*5 + LENGTH(emp.ename), ' ') AS "Hierarchy"
FROM employee emp
START WITH empno IN (SELECT empno FROM employee)
CONNECT BY PRIOR manager = empno;
which makes a subtree for every employee in the employee table from bottom to top, but I don't know how to navigate through to get to the desired result!
Here is one way to do it
with fullemployee (empno, ename, salary, key)
as
(
select A.empno, A.ename, A.salary, A.empno || '.' from
employee A
where A.manager is null
union all
select C.empno, C.ename, C.salary, D.key || '.' || C.empno from
employee C
inner join fullemployee D on C.manager = D.empno
)
select E.ename, F.ename as manager from fullemployee E
inner join fullemployee F on E.key like F.key || '%' and E.key <> F.key
where E.salary > F.salary
or equivalently
with fullemployee (empno, ename, salary, key)
as
(
SELECT empno, ename, salary, SYS_CONNECT_BY_PATH(empno, '.') || '.'
FROM employee
START WITH manager is null
CONNECT BY PRIOR empno = manager
)
select E.ename, F.ename as manager from fullemployee E
inner join fullemployee F on E.key like F.key || '%' and E.key <> F.key
where E.salary > F.salary
SQL Fiddle - http://sqlfiddle.com/#!4/37f4ae/35
This should do the work. Remove that or condition if you don't want the 'root' in your list.
select e.empno, e.ename, e.salary from employee e
inner join employee mgr on mgr.empno = e.manager
where e.salary > mgr.salary
or (e.manager = mgr.empno)