Catch multiple types of data in SQL Server - sql

I have a table (Task) like this:
Task Table
and I need answer like this:
TaskResult
I am doing the first query like this:
select
StudentID, AdmissionID, EnquiryID, EnquiryDetailsID
from
Task
where
TaskUser = 0 and BranchID = 1
If I'm getting studentID then I create second query in loop for searching the student first name and last name.
elseif I'm getting EnquiryID then I create second query in loop for searching the Enquiry first name and last name.
elseif I'm getting AdmissionID then I create second query in loop for searching the Admission guys first name and last name.
elseif I'm getting EnquiryDetailsID then I create second query in loop for searching the EnquiryDetails first name and last name.
So it creates loop in a loop and I get heavy load time on the page.
I need to combine both queries into one query. So page won't be loading.
I only have two elements i.e. taskUser and BranchID.
Please help me!! Thanks in advance !!!

So - it looks like you have an oddly organized task table, and as a result, you're going to have to do mildly weird things to query right. According to your description, a row in the task table contains either a studentId, an admissionId, an enquiryId, or an enquiryDetailId. This isn't an optimal way to do this...but I understand that sometimes you have to get by with what you have.
So, to get the names, you have to join to the source of the names...and assuming they're all over the place, in related tables, you could do something like:
select
t.StudentID,t.AdmissionID,t.EnquiryID,t.EnquiryDetailsID,x.FirstName,x.LastName
from Task t inner join Student s on t.StudentId = s.Id
union all
select
t.StudentID,t.AdmissionID,t.EnquiryID,t.EnquiryDetailsID,x.FirstName,x.LastName
from Task t inner join Admission a on t.AdmissionId = a.Id
union all
select
t.StudentID,t.AdmissionID,t.EnquiryID,t.EnquiryDetailsID,x.FirstName,x.LastName
from Task t inner join Enquiry e on t.EnquiryId = e.Id
union all
select
t.StudentID,t.AdmissionID,t.EnquiryID,t.EnquiryDetailsID,x.FirstName,x.LastName
from Task t inner join EnquiryDetail d on t.EnquiryDetailId = d.Id
...or, you can accomplish the same thing kinda inside-out:
select
t.StudentID,
t.AdmissionID,
t.EnquiryID,
t.EnquiryDetailsID,
x.FirstName,
x.LastName
from
Task t
inner join
(
select 's' source, Id, FirstName, LastName from Student union all
select 'a' source, Id, FirstName, LastName from Admission union all
select 'e' source, Id, FirstName, LastName from Enquiry union all
select 'd' source, Id, FirstName, LastName from EnquiryDetail
) as x
on
( t.StudentId = x.Id and x.source = 's' )
or
( t.AdmissionId = x.Id and x.source = 'a' )
or
( t.EnquiryId = x.Id and x.source = 'e' )
or
( t.EnquiryDetailId = x.Id and x.source = 'd' )
where
t.TaskUser=0 and t.BranchID=1

Use LEFT JOIN with COALESCE like this:
--not tested
select StudentID, AdmissionID, EnquiryID, EnquiryDetailsID,
COALESCE(s.name, e.name, d.name, ed.name) as name, etc.
from Task t
left join student s on s.id = t.studentID
left join Enquiry e on e.id = t.EnquiryID
left join Admission d on d.id = t.AdmissionID
left join EnquiryDetails ed on ed.id = t.EnquiryDetailsID
where TaskUser=0 and BranchID=1

Related

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;

SELECT Statement with correlated/nested Subquery

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

Only return results from first table with two joins

I have 3 tables. I need to get lastname, firstname, and employee number from the first table and name from another table.
In order for me to get the name on table s there needs to be a match between the slsrep columns on table s and table sw.
The issues is that I only want to return the rows from the first table (p). There is only 700 records in the first table but it is pulling 900.
Basically, I just want to look at each row in the table p and match the name from table s.
This is what I currently have:
SELECT p.LastName,
p.FirstName,
p.EmpNo,
s.Name
FROM PDDA..PhoneDirectory p
LEFT OUTER JOIN nxtsql..swsmsn sw
ON p.EmpNo = sw.EmpNo
JOIN NxtSQL..SMSN s
ON sw.slsrep = s.slsrep
WHERE sw.statustype = 1
ORDER BY
p.LastName
There are lots of ways to do this. One is to use a sub-select to get s.Name:
SELECT p.LastName, p.FirstName, p.EmpNo, (
SELECT TOP 1 s.Name
FROM NxtSQL..SMSN s
INNER JOIN nxtsql..swsmsn sw
ON sw.slsrep = s.slsrep
WHERE p.EmpNo = sw.EmpNo
AND sw.statustype = 1
) AS Name
FROM PDDA..PhoneDirectory p
ORDER By p.LastName

SQL select, 3 tables

How can I use select if I have 3 tables?
Tables:
school_subject(ID_of_subject, workplace, name)
student(ID_of_student, firstName, surname, adress)
writing(ID_of_action, ID_of_sbuject, ID_of_student)
I want to write the student's name and surname (alphabetically) who have workplace=home.
Is this possible? And how to alphabetize?
SELECT s.firstName, s.surname
FROM student S, school_subject P, writing Z
WHERE P.workplace = 'home'
AND P.ID_of_subject = Z.ID_of_subject
AND Z.ID_of_student = s.ID_of_student;
SELECT s.firstName, s.surname
FROM student S INNER JOIN writing Z
ON Z.ID_of_student = s.ID_of_student
INNER JOIN school_subject P
ON P.ID_of_subject = Z.ID_of_subject
WHERE P.workplace = 'home'
ORDER BY S.firstName, S.surname // Sort the list
To order alphabetically the result it is possible to use ORDER BY keyword. So your query becomes:
SELECT DISTINCT S.firstName, S.surname
FROM student S, school_subject P, writing Z
WHERE P.workplace = 'home' AND
P.ID_of_subject = Z.ID_of_subject AND
Z.ID_of_student = S.ID_of_student
ORDER BY S.surname, S.firstName
The DISTINCT keyword is necessary, because in writing table there are eventually more tuples given keys ID_of_subject and ID_of_student.
So this is necessary to avoid repeating firstName and surname many times.
Note that each student is identified by ID_of_student, not by firstName and surname, so as #danjok said use DISTINCT if you only want the name and surname.
If you want to select all students that satisfy your requirement (even if two or more students have the same firstName and surname), you should including ID_of_student on SELECT clause:
SELECT S.ID_of_student, S.firstName, S.surname
FROM student S
INNER JOIN writing W ON W.ID_of_student = S.ID_of_student
INNER JOIN school_subject P ON P.ID_of_subject = W.ID_of_subject
WHERE P.workplace = 'home'
ORDER BY S.firstName asc, S.surname asc

Help with query

I'm trying to make a query that looks at a single table to see if a student is in a team called CMHT and in a medic team - if they are I don't want to see the result.
I only want see the record if they're only in CMHT or medic, not both.
Would the right direction be using sub query to filter it out? I've done a search on NOT IN but how could you get to see check if its in more then 2 teams are not?
Student Team ref
1 CMHT 1
1 Medic 2
2 Medic 3 this would be in the result
3 CMHT 5 this would be in the result
So far I've done the following code would I need use a sub query or do a self join and filter it that way?
SELECT Table1.Student, Table1.Team, Table1.refnumber
FROM Table1
WHERE (((Table1.Team) In ('Medics','CMHT'))
This is Mark Byers's answer with a HAVING clause instead of a subquery:
SELECT Student, Team, ref
FROM Table1
GROUP BY Student
HAVING COUNT(Student) = 1
SELECT *
FROM students
WHERE NOT EXISTS
(
SELECT NULL
FROM students si
WHERE si.student = s.student
AND si.team = 'CMHT'
)
OR NOT EXISTS
(
SELECT NULL
FROM students si
WHERE si.student = s.student
AND si.team = 'Medic'
)
SELECT a.*
FROM Table1 a
INNER JOIN
( SELECT Student, COUNT(*) FROM Table1
GROUP BY Student
HAVING COUNT(*) = 1)b
ON (a.Student = b.Student)
how could you get to see check if its in 2 or more teams?
You can count the number of teams per student and then filter only those you want to see:
SELECT student FROM
(
SELECT student, COUNT(*) AS cnt
FROM Table1
GROUP BY student
) T1
WHERE cnt = 1
You can do it with outer join
select COALESCE(t1.Student, t2.Student) as Student,
COALESCE(t1.Team, t2.Team) as Team,
COALESCE(t1.ref, t2.ref) as ref
from
(select * from Student where Team = 'CMHT') t1
outer join
(select * from Student where Team = 'Medic') t2
on t1.Student = t2.Student
where
t1.Student is null or
t2.Student is null;