Access SQL query for sorting - ms-access

enter image description here - Relationships
Find employees who took some kind of management class (i.e., a class whose name ends with management). List employees’ last and first name, class name, and the class date. Sort the query output by last name in ascending.
I did the following, But the query is not working. Cannot find the ClassName that ends with management.
SELECT E.Last, E.First, C.ClassName, C.Date
FROM EMPLOYEES AS E, EMPLOYEE_TRAINING AS ET, CLASSES AS C
WHERE E.EmployeeID = ET.EmployeeID AND C.ClassID = ET.ClassID AND C.ClassName LIKE "Management*"
ORDER BY E.Last ASC;

Replace "Management*" with "*Management" or "%Management" because you want to find ClassName that ends with Management, not start with Management

Related

SQL-EX.ru Exercise #36

I am trying to solve exercise #36 which is List the names of head ships in the database (taking into account Outcomes table).
Head ships are the names of ships that were first in line for that class (i.e. 2 ships but 1 build before another so the first ship is the "head ship"). My result says I did says the following:
Your query returned the correct dataset on the first (available) database, but it returned incorrect dataset on the second checking database.
* Wrong number of records (less by 1)
My query is as follows:
SELECT A.name FROM Ships A
WHERE A.name = A.class
AND A.launched = (SELECT MIN(B.launched) FROM Ships B
WHERE A.name = B.name
AND A.class = B.class)
UNION ALL
SELECT A.ship
FROM Outcomes A
WHERE A.ship IN (SELECT C.ship FROM Outcomes C, Classes D
WHERE C.ship IN (SELECT ship FROM Outcomes)
AND C.ship NOT IN (SELECT name FROM Ships)
AND C.ship = D.class
)
Database is setup as follows:
The database of naval ships that took part in World War II is under consideration.
The database has the following relations:
Classes(class, type, country, numGuns, bore, displacement)
Ships(name, class, launched)
Battles(name, date)
Outcomes(ship, battle, result)
Ships in classes are arranged to a single project. A class is normally assigned the name of the first ship in the class under consideration (head ship); otherwise, the class name does not coincide with any ship name in the database.
The Classes relation includes the class name, type (bb for a battle ship, or bc for a battle cruiser), country where the ship was built, number of main guns, gun caliber (diameter of the gun barrel, in inches), and displacement (weight in tons).
The Ships relation includes the ship name, its class name, and launch year.
The Battles relation covers the name and date of a battle the ships participated; while the result of their participation in the battle (sunk, damaged, or unharmed - OK) is in the Outcomes relation.
Notes:
Outcomes relation may include the ships not included in the Ships relation.
Sunk ship can not participate in battles after that.
Now my query returns the correct answer but on the union it is not returning the correct value? My understanding is that one of the ship names does not exist in the Ships table so I picked it up from Outcomes to resolve the issue. But even that is not correct. Is there anything I am missing?
Head ships are the ships that have the same name as the class they belong too, I worked wit that and it worked:
WITH union1 (name) AS
(SELECT name FROM ships WHERE name = class
UNION SELECT ship AS name FROM outcomes
INNER JOIN classes ON classes.class = outcomes.ship)
SELECT DISTINCT name FROM union1
A simpler solution:
select name from ships where name IN (select class from classes)
UNION
select ship from outcomes where ship IN (select class from classes)
Select name from ships where name = class
union
select ship from outcomes join classes on outcomes.ship = classes.class

Multiple SQL Join

I have to write a query that retrieves data from multiple tables, I have tried all my best to get it but keeps getting stuck.
I have the following tables:
Teacher:
teacher_code
initial
name
Student:
stud_no
initial
insertions
name
birth_date
address
city
class_code
Class:
class_code
classname
Module:
module_code
modulename
Teacher_module:
teacher_code
module_code
class_code
Grade:
stud_no
module_code
date
grade
And this is the query I need to write:
Show the names of the students with associated grades for the Databases examination of 21-11-1001.
I really appreciate your time.
I'm guessing "Databases" is a modulename.
I'm hoping 21-11-1001 is the grade.date, not some sort of code.
I don't know why you listed sql-server and mysql. I'm going to assume mysql, because I never get to use natural joins in real life. I'd be assuming any schema/references anyway, so I'll just let the engine figure it out.
select s.name, g.grade
from grades g
natural join student s
natural join module m
where m.modulename='Databases'
and g.date='1001-11-21'
there you go, grades from a thousand years ago.
Something like this?:
select s.name, g.grade
from student s
join grade g on s.stud_no = g.stud_no
join module m on m.module_code = g.module_code
where m.modulename = '21-11-1001'
It depends on which column contains 21-11-1001. If it is in the module table in the modulename column, then that should work.

Rails join from association in two tables

I have to tables: Associates and Departments
One associate belongs to a department (belongs_to) and one department has many associates (has_many)
What I', trying to do is count number of associates on each department and make a pie chart with the data, i got the chart working with something basic (Department.count)
I just started with rails and I'm having issues with the query
Associate.joins(:department).group(:name).count
what i get is the following
Mysql2::Error: Column 'name' in field list is ambiguous: SELECT COUNT(*) AS count_all, name AS name FROM associates INNER JOIN departments ON departments.id = associates.department_id GROUP BY name
I tried doing a select, find and I just cant seem to get it right
If you have your associations setup correctly, I believe you should be able to do something like this:
Department.find(<some_id>).associates.count
Or if you have all the departments, and you're looping through them, let's say in a view and you want to get all the counts, you can do something like this:
#departments = Deparment.all
#departments.each do |department|
department.associates.count
end
You're associate table will need a department_id column on it.
As stated in the comment on your post, you have to resolve the ambiguous name attributed by specifying the table. You can do so either with the string as suggested, or by passing a block to group_by:
Associate.joins(:department).group_by(&:name).count

Is this possible w/ SQL?

I'm working with a SQL database for a Skills Matrix application and I need a query to return a list of employees that are qualified for a given position. Here's a brief overview of the relevant relationships:
Employee has many skills through
qualifications
Position has many
skills through requirements
Is there a efficient way to return a list of employees that have the qualifications to meet a certain position's requirements?
EDIT
employees
- id
- name
positions
- id
- title
skills
- id
- name
requirements
- position_id
- skill_id
qualifications
- employee_id
- skill_id
SELECT *
FROM employees e
WHERE NOT EXISTS (
SELECT *
FROM requirements r
WHERE r.position_id = 1234
AND NOT EXISTS (
SELECT *
FROM qualifications q
WHERE q.skill_id = r.skill_id
AND q.employee_id = e.employee_id
)
)
It will find all employees such that there are no requirement that is not filled by the employee's qualifications.
The use of nested NOT EXISTS is even mentioned in the MySQL Reference Maual
Sure, it's possible. I count seven tables there: Employee, Qualifation, EmployeeQualifications, Position, Requirement, PositionRequirements, and RequirementQualifications. If your Qualifications and Requirements will always be 1:1 (ie, they are the same thing), you can do it more simply (5 tables) like this: Employee, Position, Skill, EmployeeSkills, PositionSkills.
Once you have the tables defined, the trick to building the query is to first look for any positions for which an employee is not qualified, and then do an exclusion join with that result set back to the position table to get your results.
Yes, to achieve what you want you need, given a Position to return only those Employees, that have qualifications that collectively include all the skills the Position requires. If you retrieve these Employees, this list it will represent the list of the customers you are after.
Update
Since I do not have any experience with mysql, my reply only deals with sql server.
Try something like this:
select
qualifications.employee_id
from
qualifications
join
requirements
on
requirements.skill_id = qualifications.skill_id
where
requirements.position_id = 1234
group by
qualifications.employee_id
having
count(qualifications.skill_id) = (select count(distinct skill_id) from requirements where requirements.position_id = 1234)
Create an index on each of
employees.id
qualifications.employee_id
qualifications.skill_id
requirements.skill_id
requirements.position_id

SQL Server Reporting Services, how to best apply filters

I have a bunch of records (orders) that I want to make available to users to make reports from.
The users come from different departments, and I would like to make it, so each department can only see their own stuff.
I can't figure out how to do this the right way.
What I have now is:
- A model where I have placed a Filter on the Order table.
The filter can use GetUserID() to get the users name, but I can't figure out how I get from that to the "UserDepartment" table that maps users to specific departments.
Ofcourse, I would prefer a solution whereby I didn't have to create new access groups or edit the model for each department that someone might dream up.
Any clues?
(Using SQL server 2008)
EDIT: This link http://blogs.msdn.com/bobmeyers/articles/Implementing_Data_Security_in_a_Report_Model.aspx shows the basics of what I'm trying to do, but the author seems to assume that each record have a UserName field that can be matched.
In my case i want all users of department X to be able to access the line.
We had a similar problem to this and ended up writing a function in SQL.
The function did the following:
Received the username parameter from SRSS
Performed a lookup on the permissions table and retrieved the records (department Id's in your case).
returned the department Id's
Then our sql statement looked like this:
SELECT *
FROM ImportantData
WHERE DepartmentId IN (SELECT Id FROM fn_GetUserDepartmentAllocations(#UserName))
This did force us to modify all of the sql queries but it allowed us to do it with minimal complex logic.
The other thing that this allows for is if you have one user who transcends department boundaries: for example a manager of 2 departments.
CREATE FUNCTION [dbo].[fn_GetUserDepartmentAllocations]
(
#UserName NVARCHAR(100)
)
RETURNS
#TempPermissions TABLE
(
DepartmentId Int
)
AS
BEGIN
INSERT INTO #TempPermissions
SELECT DepartmentId
FROM DepartmentPermissions
WHERE DepartmentAllowedUsername = #UserName
RETURN
END
The main benefit to doing it this way is it also allows you to edit one place to change the entire permissions structure, you don't have to go through each and every report to change it, instead you change one place
For example you could have a manager who belongs to 2 departments but is not allowed to view them except on thursdays (I know silly example but you get the point hopefully).
Hope this helps
Pete
This assume that Users have Orders.
So, filter by users who exist in the same dept as the filter user. Don't filter orders directly.
I've guessed at schema and column names: hoep you get the idea...
SELECT
MY STuff
FROM
Order O
JOIN
UserDept UD ON O.UserCode = UD.UserCode
WHERE
EXISTS (SELECT *
FROM
UserDept UD2
WHERE
UD2.UserCode = #MYUSerCode
AND
UD2.DeptID = UD.DeptID)
--or
SELECT
MY STuff
FROM
Order O
JOIN
UserDept D ON O.UserCode = D.UserCode
JOIN
UserDept U ON D.DeptID = U.DeptID
WHERE
U.UserCode = #MYUSerCode
What you're trying to achieve is difficult using the GetUserID() method. To use that your source query would have to return a lot of redundant data, imagine something like the following:
/*
Table: User
Fields: UserID, LoginName, FullName
Table: Department
Fields: DepartmentID, Name
Table: UserDepartments
Fields: UserID, DepartmentID
Table: Order
Fields: OrderNumber, DepartmentID
*/
SELECT O.OrderNumber, O.DepartmentID, U.LoginName
FROM Order O
JOIN Department D ON D.DepartmentID = O.DepartmentID
JOIN UserDepartments UD ON UD.DepartmentID = D.DepartmentID
JOIN User U ON U.UserID = UD.UserID
This will give you more rows than you want, basically a copy of the order for each user in the department that owns the order.
Now you can apply your filter as described in the link you provided. This will filter it down to just one copy of the order rows for the current user if they're in the right department.
If this is a performance issue there's other alternatives, easiest being using a local report (.RDLC) in either ASP.NET, WinForms or WPF and passing user details off to the data call so the filtering can be done in the SQL.