Priority in SQL queries - sql

Three tables:
Employees {EmployeeID, EmployeeName}
Courses {CourseID, CourseName}
TrainingLog {LogID, EmployeeID, CourseID)
There's one position left in a course and the priority is to give it to someone who's never done a course before, then someone who has done courses but not this one, then anyone. The course must be filled.
Can the appropriate employee be found in one query?

Ya. It can be done.
Join Employees with TrainingLog on the courseId in question.
Some number of employees will not match yielding a NULL courseid.
order the set by DESC with NULLs first in the list.
rank them by rownum, and pick the first row.
if there is no first row, then there is noone to assign to the class.
otherwise,
if the first one in the list will be the person to assign.

base on the problem you want to resolve this could not be possible if you'll try to do it on query alone you have to work the logic with your application as well perhaps you'd love to create a stored procedure for this kind of conditions.

Related

If I have multiple values in a column, how can I count it in SQL?

Let me illustrate this:
Student_ID
Course
StudentID1
CourseA
StudentID2
CourseB
StudentID3
CourseA CourseB
There is an existing table that has data that looks like the one above (Not exactly Student & Course, this is more for illustration purpose) and my job is to do a count of how many students for each course. The table is very huge and I do not know how many and what are the courses are out there (Easily in thousands), so wonder if there is a way I can get a list of all these courses and their counts through SQL?
The current method that my team did is SELECT DISTINCT COURSE, COUNT(STUDENT_ID) FROM TABLE GROUP BY COURSE, but this does not work because it treats "CourseA CourseB" as its own.
There are some other columns in this table that I might need to do a SUM as well.
Appreciate any advice on this, thanks!
you could use below to find number of students for each course:
select course, count(*) as no_of_students
from table
group by course;

Looking to display records from Table A that have more than one relationship to Table B

This sounds like a very simple query but I have never needed this calculation before. I'm using SQL Management Studio and SQL Server 2008.
I have a table ct_workers which contains individual employees and a second table cs_facilities which shows the sites that they work at.
The table ct_workers has a field person which is the primary ID for each employee and has a field facility which links the employees to cs_facilities via a field guid
I'm looking to display all workers that have 2 or more facilities.
I've though about using Excel or rownumber but surely that must be a simple efficient way of doing this?
Can anyone assist please?
Thanks,
You can use a GROUP BY with HAVING
SELECT cw.person
FROM ct_workers cw
GROUP BY cw.person
HAVING COUNT(DISTINCT cw.facility) >= 2
Your question suggests that you can use aggregation:
select w.person
from ct_workers w
group by w.person
having min(w.facility) <> max(w.facility); -- at least 2 values
However, if the person is the unique key in ct_workers, then a person can only be in one facility. So, your question would not make sense. You should actually have a junction table with one row per person and per facility.

Oracle SQL, not exist and count

I am currently stuck with my assignment. I am not trying to be lazy but I can't seems to find a solution and my teacher guided me by saying to use not exist or count.
I need to find patients name who have been treated by all the doctors. Currently I am just using plain intersect SQL command for each doctor name (In the question, there are only 3 doctors) but of course its not realistic when there are 100's of doctors name.
The scheme is as below.
Patient (PatientID, FamilyName, GivenName)
Account (ProviderNo, PatientID)
Doctor (ProviderNo, Name)
Any help would be greatly appreciated.
I won't provide you the exact Query.
But here is the psuedo code:
group PatientId in Account where its distinct ProviderNo count should be
equal to no. of Doctors

How to create views against a hierarchical table

I am learning how to create view using SQL server. I am trying to add a view called Managers in the Northwind database that shows only employees that supervise other employees. This is what I have so far.
Create View Manager_vw
As
Select LastName,
FirstName,
EmployeeID
From Employees
Where
What I am stuck on is how and I going to put in supervise other employees. I am not to sure how to do this. If someone can help me understand how to do this.
In northwind.dbo.employees you would find employees who supervise other employees by looking the reportsto column. Basically you want to return employees whose id is in the reportsto column in another row. That can be done like this:
SELECT LastName,
FirstName,
EmployeeID
FROM employees E
WHERE EXISTS(SELECT * FROM Employees WHERE reportsTo = E.EmployeeID)
The EXISTS is like a JOIN but is usually implemented as a "semi-join" which will stop processing after it finds a singe match (rather than finding all the subordinate employees which would take extra work) Because it doesn't return any additional records, you also save the cost of the additional step to eliminate duplicates (a JOIN would do more work to process the join, and even more work to undo the work that wasn't necessary by doing a DISTINCT.)
You'll notice that I reference E.EmployeeID in the subquery, which relates the subquery to the outer query, this is called a Correlated Subquery.
A word of caution: Views have their place in a DB but can easily be misused. When an engineer comes to the database from an OO background, views seem like a convenient way to promote inheritance and reusability of code. Often people eventually find themselves in a position where they have nested views joined to nested views of nested views. SQL processes nested views by essentially taking the definition of each individual view and expanding that into a beast of a query that will make your DBA cry.
Also, you followed excellent practice in your example and I encourage you to continue this. You specified all your columns individually, never ever use SELECT * to specify the results of your view. It will, eventually, ruin your day. You'll see I do have a SELECT * in my EXISTS clause but EXISTS does not return a resultset and the optimizer will ignore that in that specific case.
Here's another option:
SELECT DISTINCT manager_tbl.*
FROM Employees AS staff_tbl
JOIN Employees AS manager_tbl
ON staff_tbl.ReportsTo = manager_tbl.EmployeeID
Adapted from this site. There are a number of example queries there that you might find interesting and useful.
Notes:
Using the DISTINCT keyword because a single manager could have more than one direct report. DISTINCT will omit the repetition caused by such a one-to-many relationship.
The Employees table in the Northwind database is an example of a hierarchical relationship modeled in a single table.
All together:
CREATE VIEW Manager_vw
AS
SELECT DISTINCT manager_tbl.*
FROM Employees AS staff_tbl
JOIN Employees AS manager_tbl
ON staff_tbl.ReportsTo = manager_tbl.EmployeeID

sql resultset order defined?

Say I've employee table where any employee can be related to any other employee (many to many). Each employee has many characteristics that are stored separately.
emp: id,name
related: name,emp1role,emp1id,emp2role,emp2id
chars: empid,name,value
I want to get all the characteristics of employees who are related via 'xxx' along with the relation. I am currently using this query:
SELECT c.empid, c.Name, c.Value
FROM chars as c, related as r
WHERE r.name='xxx' AND (r.emp1id=c.empid OR r.emp2id=c.empid)
This works and it gives related employees one after another i.e. if emp22 & emp43 are related via 'xxx' then I am getting chars of emp43 followed by emp22 and so on. This way I am able to know which two employees are related (which is needed). However, I want to know if this order is mere luck or is it well-defined. This is in SQLite.
If it is not defined way, how else can I do it? Also, I need to know their respective roles. I want to preferably do it in one query. Can you think of some other query?
Thanks in advance,
Manish
PS: These are not actual tables. They are here for simplicity of asking question.
In SQL, ordering of the result is undefined unless you have an explicit ORDER BY clause in your query. So I believe you want:
SELECT c.empid, c.Name, c.Value
FROM chars as c, related as r
WHERE r.name='xxx' AND (r.emp1id=c.empid OR r.emp2id=c.empid)
ORDER BY c.empid ASC
I tend to add a unique field (such as a primary key) at the end, to if not get an obvious ordering when there are multiple records matching in all other order fields, at least get deterministic ordering. But that's largely a matter of style and choice; it's by no means required.