What would be the result of the following query? - sql

The following query I tried...
select d.deptID, max(tt.total)
from dept d,
(select d.deptID, d.deptName, sum(days) as total
from vacation v, employee e, dept d
where v.empId = e.empID
and d.deptID = e.deptID
group by d.deptID, d.deptName) tt
where d.deptID = tt.deptID
group by d.deptName;
--having max(tt.total);

Try using limit since your inner query already does the calculation.
select TOP 1 * from (
select d.deptID, d.deptName, sum(days) as total
from vacation v, employee e, dept d
where v.empId = e.empID
and d.deptID = e.deptID
group by d.deptID, d.deptName)
order by total desc;
Depends on the dbms you're using.. this is for mysql
In oracle use where rownum = 1
In sql server use SELECT TOP 1 *

Using Top:
Select top 1 with ties * from
(Select D.DepartmentName, sum(V.Days) as SumDays
from Vacations V
inner join Employee E on E.EmployeeID=V.EmployeeID
inner join Department D on D.DepartmentID=E.DepartmentID
group by D.DepartmentName)SumDays
Order by SumDays desc

Try like this,
SELECT TOP 1 d.departmentname,
Sum(v.days) AS vacations
FROM employee emp
INNER JOIN department d
ON d.departmentid = emp.departmentid
INNER JOIN vacations v
ON v.employeeid = emp.employeeid
GROUP BY d.departmentname
ORDER BY 2 DESC

Related

Select both row number and count from oracle

I'm trying to select records with pagination, and I need the total number of records so that I can display the number of records and pages on the UI.
The query I'm using is as below but it always returning the totalcount as 1.
WITH cteEmp AS
(SELECT e.empid, e.empname, d.deptid, d.deptname
FROM hr.Emp e
INNER JOIN hr.dept d ON e.deptid = d.deptid)
Select * from (SELECT row_number() over (order by hr.empid desc) rn, Count(*) totalcount,
C.empName FROM CTEPO C
LEFT JOIN hr.emphistory ON C.empid=hr.empid
GROUP BY c.empid,hr.empid) where rn>0 and rn<= 100
You can try this maybe it'll work for you:
(SELECT e.empid, e.empname, d.deptid, d.deptname
FROM hr.Emp e
INNER JOIN hr.dept d ON e.deptid = d.deptid)
Select * from (SELECT row_number() over (order by hr.empid desc) rn,
count(*) OVER (ORDER BY hr.empid desc ) AS totalcount
C.empName FROM CTEPO C
LEFT JOIN hr.emphistory ON C.empid=hr.empid
GROUP BY c.empid,hr.empid) where rn>0 and rn<= 100

How to get result if exactly one match inner join

How can I write a query to join two tables and return result if exactly one match in there. I have to discard results if zero match and more than one match.
All I am looking for is to extend the INNER JOIN. Let me just get to the point. I have two tables Dept & Emp. One Dept can have multiple Emp's & not the other way around.
Table Dept
Table Emp
I need to JOIN it on Dept_id
Expected Results
You can join with a not exists condition:
select d.*, e.emp_id, e.emp_name
from dept d
inner join emp e
on d.dept_id = e.dept_id
and not exists (
select 1
from emp e1
where e1.dept_id = d.dept_id and e1.emp_id != e.emp_id
)
One alternative to existing solutions can be one using analytics (window functions),
instead of joining twice:
select dept_id, dept_name, emp_id, emp_name
from
(
SELECT
d.Dept_id, d.Dept_name, e.Emp_id, e.Emp_Name,
count(*) over (partition by d.dept_id) cnt1
FROM d
INNER JOIN e
ON d.Dept_id = e.Dept_id
) where cnt = 1;
You could use a subquery for group by dept_id haing count = 1
select t.dept_id, dept.dept_name, emp.Emp_name
from (
select dept_id
from emp
group by dept_id
having count(*) = 1
) t
INNER JOIN dept on t.dept_id = dept.dept_id
INNER JOIN emp ON t.dept_id = emp.dept_id
You can phrase this as an aggregation query in Oracle:
select d.dept_id, d.dept_name,
max(e.emp_id) as emp_id,
max(e.emp_name) as emp_name
from dept d inner join
emp e
using (dept_id)
group by d.dept_id, d.dept_name
having count(*) = 1;
This works because if there is only one match, then max() returns the value from the one row.
Also, try below query;
SELECT a.depid dept_id,dept_name,emp_id,emp_name
FROM
(SELECT case WHEN count(*)=1 THEN dept_id END depid FROM emp GROUP BY dept_id) a INNER JOIN emp ON depid=dept_id
INNER JOIN dept b ON a.depid = b.dept_id
WHERE depid IS NOT NULL
Another way would be
select d.dept_id, d.dept_name, e.emp_name
from emp e
join dept d on d.dept_id = e.dept_id
where e.dept_id in
( select dept_id from emp group by dept_id having count(*) = 1 )

Query to get employee of different departments

I have 3 tables: Employee, Department and employeeProject.
The relation between employee and employeeproject is one-to-many. The relation between employee and department is many-to-one.
I want to write a query to select 10 employees who have worked in projects 3 and 4. The query should return employees of different departments if possible.
The query below kind of works. The only problem is that the relationship between employee and employeeproject is one-to-many, so it might return the same employee number multiple times.
I cannot use distinct because all fields in the order by clause should be used in select when using distinct.
select top 10 empid from employee e
inner join department d on d.depId=e.depid
inner join employeeProject p on p.empid=e.empid
where p.projectID in (3,4)
order by row_number() over(partition by e.depId order by e.empid)
Bit of a guess, but use an EXISTS?
SELECT TOP 10 e.empid
FROM employee e
JOIN department d ON e.depid = d.depid
WHERE EXISTS (SELECT 1
FROM employeeproject p
WHERE p.emdid = e.empid
AND p.projectid IN (3,4))
ORDER BY e.depid, e.empid;
I suggest aggregating by employee, and then using an assertion the HAVING clause:
SELECT TOP 10 e.empid
FROM employee e
INNER JOIN department d
ON d.depId = e.depid
INNER JOIN employeeProject p
ON p.empid = e.empid
WHERE
p.projectID IN (3,4)
GROUP BY
e.empid
HAVING
MIN(p.projectID) <> MAX(p.projectID);
If the minimum and maximum projectID are not equal for a given employee, after restricting to only projects 3 and 4, then it implies that this employee meets the criteria.
Why not just use select distinct?
select distinct top 10 empid
from employee e inner join
employeeProject p
on p.empid = e.empid
where p.projectID in (3, 4)
order by row_number() over (partition by e.depId order by e.empid);
Note that the department table is not needed.
Alternatively,
select top (10) e.*
from employee e
where exists (select 1
from employeeprojects ep
where p.emdid = e.empid and
p.projectid in (3, 4)
)
order by row_number() over (partition by e.depid order by newid());

I need sql query to merge info from 2 tables

i`m new in SQL and i need a tip. I got 2 tables ( employee and department ),
employee table as E:
id (int), name(nvarchar), gender(nvarchar), departmentID(int), dateofbirth(datetime)
department table as D :
dep_id(int), name(nvarchar), location(nvarchar), boss_id(int)
That`s what i need as output table:
E.id / E.name / D.name / D.location / (and last which i cant get with simple join is:) D.boss.name (not simple boss id but real employee name from E table)
Just simple question for advanced people :-)
Join the table a second time for the boss. (This is assuming that boss_id FK's to Employee)
SELECT
E.Id,
E.Name,
D.Name,
D.Location,
B.Name
FROM Employee E
INNER JOIN Department D on E.DepartmentID = D.Dep_id
INNER JOIN Employee B ON D.Boss_id = B.Id
You can write a query using cte as well:
WITH CTE AS(
Select
e.ID,
e.name,
d.boss_id,
d.Location as DepartmentLocation,
d.name as DepartmentName
From Employee e
INNER JOIN Department d on d.boss_id =E.id
)
Select c.id, c.name, e.name as BossName, c.DepartmentLocation, c.DepartmentName
from cte c
Inner Join Employee e1 on e1.id=c.boss_id
SELECT e.Id, e.Name, d.Name, d.Location,
(
SELECT e2.Name
FROM tblEmployee as e2
WHERE e2.id = d.boss_id
) AS [Boss name]
FROM tblEmployee as e
INNER JOIN tblDepartment as d
ON e.DepartmentID = d.dep_ID

SQL Server 2005 - Nested recursive query :(

I have a query that I need to execute that I do not know how to structure.
I have a table called Employees. I have another table called Company. There is a third table called Files. As you can imagine, a Company has Employees, and Employees have Files.
I need to list out all of the Employees in my database. The challenge is, I need to list the total number of Files in the same company as the Employee. I have tried variations on the following without any luck:
SELECT
e.FirstName,
e.LastName,
e.Company,
(SELECT COUNT(*) FROM Files f WHERE f.EmployeeID IN (SELECT [ID] FROM Employees e2 WHERE e2.CompanyID=e.CompanyID)) as 'FileCount'
FROM
Employees e
What am I doing wrong? Thank you!
Try this:
SELECT
e.FirstName,
e.LastName,
e.Company,
(
SELECT COUNT(*)
FROM Files f
JOIN Employees e2 ON f.EmployeeID = e2.id
WHERE e2.CompanyID = e.CompanyID
) as 'FileCount'
FROM
Employees e
There are a lot of ways to get that. If the performance is a concern, this is more optimal according to estimated execution plan costs.
SELECT
e.FirstName,
e.LastName,
e.Company,
COUNT(f.FileId)
FROM
Employees e
INNER JOIN Files f ON e.EmployeeID = f.EmployeeID
GROUP BY
e.FirstName,
e.LastName,
e.Company
A solution with no correlation in SELECT clause. Probably quicker...
SELECT
e.FirstName,
e.LastName,
e.Company,
foo.FileCount
FROM
Employees e
JOIN
(
SELECT
COUNT(*) AS FileCount, --OR COUNT(DISTINCT something) ?
e2.Company, f.EmployeeID
FROM
Files f JOIN Employees e2 ON f.EmployeeID = e2.id
GROUP BY
e2.Company, f.EmployeeID
) foo ON e.Company = foo.Company AND e.id = foo.EmployeeID
How about:
SELECT
e.FirstName,
e.LastName,
e.Company,
select count(*) from Files f, Employees e where f.EmployeeID=e.EmployeeID and e.CompanyID=emp.CompanyID
FROM
Employees emp
WITH FilesPerCompany (CompanyID, NumberOfFiles)
AS (SELECT c.ID AS CompanyID,
COUNT(*) AS NumberOfFiles
FROM Companies c
INNER JOIN Employees e ON c.ID = e.CompanyID
INNER JOIN Files f ON e.ID = f.EmployeeID
GROUP BY c.ID
)
SELECT e.FirstName,
e.LastName,
e.Company,
COALESCE(s.NumberOfFiles, 0) AS NumberOfFilesPerCompany
FROM Employees e
LEFT JOIN FilesPerCompany s
ON s.CompanyID = e.CompanyID
The following statement uses recursive joins to iterate down employees who manage other employees who manage other employees .... etc. Our structure is a little convoluted as the management structure is role based which actually allows an employee to have more than 1 manager. You can add a reference to Files within this recursion.
WITH Manager as
(SELECT c.Forenames + ' ' + c.Surname as Employee,
c2.Forenames + ' ' + c2.Surname AS Manages,
c.accountid AS AccountID, c.[Status] AS [Status]
FROM [intranet].[dbo].[tblContact] c
LEFT JOIN tblContactPost cp ON cp.contactid = c.contactid
LEFT JOIN tblPost p ON p.ParentRoleId = cp.RoleID AND p.ParentPostArea = cp.PostArea AND p.ParentPostNo = cp.PostNo
INNER JOIN tblContactPost cp2 ON cp2.RoleId = p.RoleId AND cp2.PostArea = p.PostArea AND cp2.PostNo = p.PostNo
INNER JOIN tblContact c2 ON c2.ContactID = cp2.ContactId
)
,jn AS
(SELECT Employee, Manages
FROM Manager
Where AccountID = 'ad\lgardner' AND [Status] = 'A'
UNION ALL
SELECT c.Employee, c.Manages
FROM jn as p JOIN Manager AS c
ON c.Employee = p.Manages
)
SELECT jn.Employee, jn.Manages
From jn
Order BY 1