SELECT Statement with correlated/nested Subquery - sql

I have two tables in my database, Department & DepartmentErrors.
The DepartmentErrors table contains a column called 'Error
I would like to run a select statement on the Department table, matching any related occurrences of that department within DepartmentError, where the Error value matches a number. I would then like to append a column onto that result set, for each department, containing how many rows matching that department ID & Error value have appeared within the department error table. This is my code so far:
SELECT DISTINCT
Department.DeptID,
Name,
Size,
Location,
(
SELECT COUNT(*)
FROM DepartmentErrors
INNER JOIN Departments ON DepartmentErrors.DeptID = Departments.DeptID
WHERE Error = 2
) AS ErrorCount
FROM Departments
INNER JOIN DepartmentErrors ON Departments.DeptID = DepartmentErrors.DeptID
WHERE DepartmentErrors.Error = 2

Try this one -
SELECT d.DeptID,
d.Name,
d.Size,
d.Location,
e.ErrorCount
FROM Departments d
JOIN (
SELECT DeptID, ErrorCount = COUNT(*)
FROM DepartmentErrors
WHERE Error = 2
GROUP BY DeptID
) e ON d.DeptID = e.DeptID

Related

How to get count of registered sets combination and non registered sets as '0' value

I had 2 individual tables named manager, employee.
In the manager table we have ID, a list of managers, in the employee table we have ID, a list of employees, and another column named manager_id as a foreign key. Total 20 combinations
Now there is another table called registration which has manager and employee as separate columns along with other columns. I want a select query of All 20 manager and employee combinations for which non registered combinations should appear as '0'.
I tried with below query but not getting expected output
Query:
select r.manager,r.employee,count(*)
from registration r
group by r.manager,r.employee
union all
select s.manager, i.employee,null
from manager m, employee e
where m.id = e.manager_id
---> It is showing output in a way where the registration table list is coming first with count and later with all 20 combinations as null value in count column
I don't know the exact column names of the registration table, but the query should be something like this:
select
e.id,
e.manager_id,
(case r.employee_id is null then 0 else 1 end) as is_registered
from
employee e
left join registration r
on r.employee_id = e_id and r.manager_id = e.manager_id
This is the query I modified
select m.manager, e.employee,
sum(case when r.employee is null then 0 else 1 end) as total
from employee e
left join registration r on r.employee = e.employee
left join manager m on m.id = e.manager_id
group by m.manager, e.employee, r.employee

SELECT and JOIN to return only one row for each employee

I have a user table that stores the employeeId, lastName, firstName, department, hire date and mostRecentLogin.
I have another table that stores the employeeId, emailAddress.
The emailAddress table can have multiple rows for an employee if they have multiple email addresses.
I'm trying to return results that only show one row for each employee. I don't care which email address, just as long as it only picks one.
But all the queries I've tried always return all possible rows.
Here is my most recent attempt:
select *
from EmployeeInfo i
left join EmployeeEmail e ON i.employeeId = e.employeeId
where i.hireDate = 2015
and employeeId IN (
SELECT MIN(employeeId)
FROM EmployeeInfo
GROUP BY employeeId
)
But then again, this returns all possible rows.
Is there a way to get this to work?
Use a sub-query instead of a join:
select *
, (select top 1 E.EmailAddress from EmplyeeEmail E where E.employeeId = I.employeeId)
from EmployeeInfo I
where I.hireDate = 2015;
Note: If you change your mind and decide you do have a preference as to which email address is returned then just add an order by to the sub-query - otherwise it is truly unknown which one you will get.
This should work.
SELECT *
FROM EmployeeInfo
Left JOIN EmployeeEmail
ON EmployeeInfo.employeeId = EmployeeEmail.employeeId
WHERE EmployeeInfo.hireDate = '2015'
GROUP BY EmployeeInfo.employeeId;

For each employee with dependent(s), list their last name and the name of their oldest dependent. Display the results in sequence by dependent’s name

SELECT E.Lname,D.Dependent_name
FROM EMPLOYEE as E , DEPENDENT as D
WHERE
E.ssn=D.Essn
AND
D.Bdate = (SELECT MIN(Bdate) FROM DEPENDENT
WHERE Bdate IS NOT NULL)
This does work but it just show for 1 employee
Link to DB:
https://www.db-fiddle.com/f/xhEj2sAgdTMABBkCtJvmoC/0#&togetherjs=z3CKywAccH
As it is, your subquery returns the minimum bdate over the whole table, resulting in only the empolyee that has the oldest dependant being filtered in. As commented by #PM77-1, you would need to correlate your subquery with the employee that you are currently processing.
SELECT E.Lname,D.Dependent_name
FROM
EMPLOYEE as E
INNER JOIN DEPENDENT as D ON E.ssn=D.Essn
WHERE D.Bdate = (
SELECT MIN(Bdate)
FROM DEPENDENT
WHERE Essn = E.ssn
)
ORDER BY 2, 1;
Another, probably more efficient option, is to use Postgres window function ROW_NUMBER() to assign a row number to each record in the group made of all dependents of a given employee, ordered by date of birth. An outer query can then filter in the first record in each group :
SELECT x.lname, x.dependent_name
FROM (
SELECT
e.lname,
d.dependent_name,
ROW_NUMBER() OVER(PARTITION BY e.ssn ORDER BY d.bdate) rn
FROM employee e
INNER JOIN dependent d ON e.ssn = d.essn
) x WHERE x.rn = 1
ORDER BY 2, 1;
Demo on DB Fiddle
select a.lname, a.dependent_name
from
(
select e.lname, d.dependent_name, d.bdate, e.ssn
from employee e, dependent d
where e.ssn=d.essn
order by d.dependent_name, e.lname
)a
where a.bdate= (select min(bdate) from dependent
where dependent.essn= a.ssn)
order by a.lname;
This displays the names of three employees > Smith, Wallace, Wong with their corresponding eldest dependents > Elizabeth, Abner, Joy.
Hope this solves the problem.

SQL - Select highest value when data across 3 tables

I have 3 tables:
Person (with a column PersonKey)
Telephone (with columns Tel_NumberKey, Tel_Number, Tel_NumberType e.g. 1=home, 2=mobile)
xref_Person+Telephone (columns PersonKey, Tel_NumberKey, CreatedDate, ModifiedDate)
I'm looking to get the most recent (e.g. the highest Tel_NumberKey) from the xref_Person+Telephone for each Person and use that Tel_NumberKey to get the actual Tel_Number from the Telephone table.
The problem I am having is that I keep getting duplicates for the same Tel_NumberKey. I also need to be sure I get both the home and mobile from the Telephone table, which I've been looking to do via 2 individual joins for each Tel_NumberType - again getting duplicates.
Been trying the following but to no avail:
-- For HOME
SELECT
p.PersonKey, pn.Phone_Number, pn.Tel_NumberKey
FROM
Persons AS p
INNER JOIN
xref_Person+Telephone AS x ON p.PersonKey = x.PersonKey
INNER JOIN
Telephone AS pn ON x.Tel_NumberKey = pn.Tel_NumberKey
WHERE
pn.Tel_NumberType = 1 -- e.g. Home phone number
AND pn.Tel_NumberKey = (SELECT MAX(pn1.Tel_NumberKey) AS Tel_NumberKey
FROM Person AS p1
INNER JOIN xref_Person+Telephone AS x1 ON p1.PersonKey = x1.PersonKey
INNER JOIN Telephone AS pn1 ON x1.Tel_NumberKey = pn1.Tel_NumberKey
WHERE pn1.Tel_NumberType = 1
AND p1.PersonKey = p.PersonKey
AND pn1.Tel_Number = pn.Tel_Number)
ORDER BY
p.PersonKey
And have been looking over the following links but again keep getting duplicates.
SQL select max(date) and corresponding value
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
SQL Server: SELECT only the rows with MAX(DATE)
Am sure this must be possible but been at this a couple of days and can't believe its that difficult to get the most recent / highest value when referencing 3 tables. Any help greatly appreciated.
select *
from
( SELECT p.PersonKey, pn.Phone_Number, pn.Tel_NumberKey
, row_number() over (partition by p.PersonKey, pn.Phone_Number order by pn.Tel_NumberKey desc) rn
FROM
Persons AS p
INNER JOIN
xref_Person+Telephone AS x ON p.PersonKey = x.PersonKey
INNER JOIN
Telephone AS pn ON x.Tel_NumberKey = pn.Tel_NumberKey
WHERE
pn.Tel_NumberType = 1
) tt
where tt.rn = 1
ORDER BY
tt.PersonKey
you have to use max() function and then you have to order by rownum in descending order like.
select f.empno
from(select max(empno) empno from emp e
group by rownum)f
order by rownum desc
It will give you all employees having highest employee number to lowest employee number. Now implement it with your case then let me know.

Query Multiple Columns Within a Table

I have a table of employees that are formatted as follows:
EMPLOYEE (FNAME,MINIT,LNAME,SSN(PK),BDATE,SUPERSSN(NULLABLE))
I need to query every employee and retrieve the following information:
FNAME(employee),LNAME(employee),SUPERSSN,(super)FNAME,(super)LNAME
UPDATED
After running this query:
SELECT A.FNAME,A.LNAME,A.SUPERSSN,B.FNAME,B.LNAME
FROM EMPLOYEE
A LEFT JOIN EMPLOYEE B
ON A.SUPERSSN = B.SSN;
The results were close, but when the superssn was null (CEO/Boss) it caused the remaining rows to populate as null also and did not populate with the actual supervisors ssn. I'm trying to use an IF statement to fix the problem with having a SuperSSN that is null, but I'm receiving the error: ORA-00905: missing keyword.
Below is the query that I ran that generated the error.
SELECT A.FNAME,A.LNAME,A.SUPERSSN,B.FNAME,B.LNAME
FROM EMPLOYEE A LEFT IF A.SUPERSSN <> 'NULL'
JOIN EMPLOYEE B ON A.SUPERSSN = B.SSN;
Select A.FName,
A.LNAme,
A.SuperSSN,
B.FName,
B.LName
from Employee A
Left Join Employee B
On A.SuperSSN = B.SSN