SQL select / group - sql

I am a student this is homework. I'm getting tired and confused. Any advice will be appreciated.
I have two tables.
Employee has the following columns:
Last_name
First_name
Address
Phone
Job_title(FK)
Wage
Job_title has
job_title(PK)
EEO classification
Job_description
Exempt_Non_Exempt
I need to select the employees’ last names and group them by salary within job titles that are grouped into exempt and non-exempt.
I'm using sql server to check my work but it needs to be hand scripted.

Can you provide sample data? Because it's not clear to me what the data type for JOB_TITLE.exempt_non_exempt is, or what is to be accomplished by the specified grouping criteria - EMPLOYEE.last_name will be mostly unique (but it can't be guaranteed due to the Mr. Smith principle), so it sounds like there's a need for aggregate function use.
Based on what I've read, this looks to be what you're after:
SELECT e.last_name, e.wage, jt.exempt_non_exempt
FROM EMPLOYEE e
JOIN JOB_TITLE jt ON jt.job_title = e.job_title
GROUP BY e.last_name, e.wage, jt.exempt_non_exempt
You join on the foreign/primary key to get valid data from both tables.
The GROUP BY clause is where you define grouping, but SQL standard is that if you specify columns in the SELECT clause without being wrapped in aggregate functions (IE: COUNT/MAX/MIN/etc), then those columns need to be specified in the GROUP BY.

Related

Microsoft SQL server select statements on multiple tables?

so I've been struggling with some of the select statements on multiple tables:
Employee table
Employee_ID
First_Name
Last_Name
Assignment table
Assignment_ID
Employee_ID
Host_Country_arrival_Date
Host_Country_departure_Date
Scheduled_End_Date
I'm being asked to display query to display employee full name, number of days between the host country arrival date and host country departure date, number of days between today's date and the assignment scheduled end date and the results sorted according to host country arrival date with the oldest date on top.
also, I'm not familiar with the sort function in SQL server..
Here's my query and I've been getting syntax errors:
SELECT
First_Name
Last_Name
FROM Employee
SELECT
Host_Country_Arrival_Date
Host_Country_Departure_Date
FROM Assignment;
So, Basically what your code is doing is 2 different queries. The first getting all the employees names, and the second one getting the dates of the assignments.
What you'll want to do here is take advantage of the relationship between the tables using a JOIN. That is basically saying "Give me all employees and all of HIS/HERS assignments". So, for each assignment that the employee has, it will bring a row in the result with his name and the assignment info.
To get the difference between days you use DATEDIFF passing 3 parameters, the timespan in which to calculate the difference, the first and the second date. It will then Subtract the first one from the second one and give you the result in the selected timespan.
And finnaly the sorting: Just add 'ORDER BY' followed by each column that you want to use for ordering and then specify if you want it ascending (ASC) or descending (DESC).
You can check how I would answer the if that question was proposed to me in a coding challenge.
SELECT
CONCAT(E.First_Name,' ', E.Last_Name) FullName,
DATEDIFF(DAY,Scheduled_End_Date,getdate()) DaysTillScheduledDate,
DATEDIFF(DAY,Host_Country_Arrival_Date,Host_Country_Departure_Date) DaysTillScheduledDate
FROM Employee As E --Is nice to add aliases
Inner Join
Assignment As A
on E.Employee_ID = A.Employee_ID -- Read a little bit about joins, there are a lot of material availabel an its going to be really necessary moving forward with SQL
order by Host_Country_Arrival_Date DESC -- Just put the field that you want to order by here, desc indicates that it should be descending
You should use a JOIN to link the tables together on Employee_ID:
SELECT
First_Name,
Last_Name,
Host_Country_Arrival_Date,
Host_Country_Departure_Date
FROM Employee
JOIN Assignment ON Assignment.Employee_ID = Employee.Employee_ID;
What this is saying basically is that for each employee, go out to the assignments table and add the assignments for that employee. If there are multiple assignments, the employee columns will be repeated on each row with the assignment columns for the assignment.
You need to look for the join and group by. Please find this link for reference tutorial
For now you may try this...
SELECT
CONCAT(Emp.First_Name,' ', Emp.Last_Name) FullName,
DATEDIFF(DAY,Scheduled_End_Date,getdate()) DaysTillScheduledDate,
DATEDIFF(DAY,Host_Country_Arrival_Date,Host_Country_Departure_Date) DaysTillScheduledDate
FROM Employee As Emp Inner Join Assignment As Assign on Emp.Employee_ID = Assign.Employee_ID
order by Host_Country_Arrival_Date DESC

Do table names always have to be in front of fields when using sql joins?

Say I have a query:
select
Last_Name,
First_Name,
e.EmployeeID
from
employee e
join
Employee_his eh on e.EmployeeID = eh.EmployeeID
First name and Last name are part of the employee table while employeeId is part of both.
Does adding the table alias e in front of last_name, first_name alter the statement in any way? I thought not but am told it will give me the wrong answer. Sorry about the simple question, it's a hard thing to look up.
This is your query:
select Last_Name, First_Name, e.EmployeeID
from employee e join
Employee_his eh
on e.EmployeeID = eh.EmployeeID;
In this case, the qualified names are needed, because EmployeeId --
with no qualification -- would be ambiguous. Which table would the column be referring to?
When you have multiple tables in a query, you should qualify all column names, so it is clear what the query is doing -- for others reading the query and for you months later.
I should note that ANSI SQL has the using clause. In many databases, the query could be written as:
select Last_Name, First_Name, EmployeeID
from employee e join
Employee_his eh
using (EmployeeId);
However, SQL Server does not support the using clause.
If both tables have a field with the same name, then yes, you need to have the table name or an alias in front of the field name.

Display all results queried on PostgreSQL where the JOINING value is missing

I have two tables on PostgreSQL, namely: employees and employers.
There is data in each of these tables.
Columns in employees: employee_id, employee_name, employer_id.
Columns in employers: employer_id, employer_name.
I want to display all employee_name's that don't have an associating employer_name.
I used the below query:
SELECT DISTINCT a.employee_name, b.employer_name
FROM employees a
NATURAL JOIN employers b
WHERE a.employee_name LIKE 'Jack';
NB!
I have also tried adding in the below to my query:
COALESCE(b.employer_name, '') = ''
Problem:
If there is no record in the employer table containing the associating employee_id value, the query returns nothing all. I am assuming this is because there is nothing for the two tables to join on?... But I would like to at least find all employees that don't have an employer. I would ideally like the employer_name value in my result to either return: blank/''/NULL.
Your assistance is greatly appreciated.
select employees.employee_name ,employers.employer_name
from employees
left join employers
on employees.employee_id = employees.employee_id
where employers.employer_name is NULL
Use a LEFT JOIN:
SELECT a.employee_name,
COALESCE(b.employer_name, 'NA') AS employer_name
FROM employees a
LEFT JOIN employers b
ON a.employer_id = b.employer_id
WHERE b.employer_id IS NULL
Your current query has several problems, first of which is that you are using a NATURAL JOIN, which should behave link an INNER JOIN, discarding employee records which do not match to any employer. Instead, by using LEFT JOIN, we can retain all employee records, regardless of whether or not they have an employer. The WHERE clause checks for NULL in the joined table, with NULL indicating that the employee did not match to any employer.
Your table name employees table is a little odd, IMO. There is a design 'rule of thumb' that says a table models either an entity or the relationship between entities but not both. To demonstrate this oddness, consider the relational operation is
employees MINUS employers
...which suggests something is off.
Another symptom of this design problem is that the employer_id in the employees table must have some kind of placeholder to represent the predicate employee has no employer, possibly a null (and nulls are to be avoided, IMO).
I suggest you fix this design by introducing a third table to model the relationship between an employee and their employer. Herein lies another design problem: shouldn't this new table be named employees? In other words, isn't the very definition of an employee a person who has an employer?
Consider this design instead:
People: person_id, person_name
Employers: employer_id, employer_name
Employees: employer_id, person_id
To find the names of people who are not employees in pseudo-relational notation:
People MINUS Employees { person_name }
SQL is quite a bit more verbose:
SELECT DISTINCT person_name
FROM People
NATURAL JOIN
( SELECT person_id FROM People
EXCEPT
SELECT person_id FROM Employees ) t;
Note your original query needlessly uses range variables a and b. One of the benefits of NATURAL JOIN is the elminiation of duplicate column names. Range variables with NATURAL JOIN always looks odd to me!

Ms-Access: counting from 2 tables

I have two tables in a Database
and
I need to retrieve the number of staff per manager in the following format
I've been trying to adapt an answer to another question
SELECT bankNo AS "Bank Number",
COUNT (*) AS "Total Branches"
FROM BankBranch
GROUP BY bankNo
As
SELECT COUNT (*) AS StaffCount ,
Employee.Name AS Name
FROM Employee, Stafflink
GROUP BY Name
As I look at the Group BY I'm thinking I should be grouping by The ManID in the Stafflink Table.
My output with this query looks like this
So it is counting correctly but as you can see it's far off the output I need to get.
Any advice would be appreciated.
You need to join the Employee and Stafflink tables. It appears that your FROM clause should look like this:
FROM Employee INNER JOIN StaffLink ON Employee.ID = StaffLink.ManID
You have to join the Eployee table twice to get the summary of employees under manager
select count(*) as StaffCount,Manager.Name
from Employee join Stafflink on employee.Id = StaffLink.EmpId
join Employee as Manager on StaffLink.ManId = Manager.Id
Group by Manager.Name
The answers that advise you on how to join are correct, assuming that you want to learn how to use SQL in MS Access. But there is a way to accomplish the same thing using the ACCESS GUI for designing queries, and this involves a shorter learning curve than learning SQL.
The key to using the GUI when more than one table is involved is to realize that you have to define the relationships between tables in the relationship manager. Once you do that, designing the query you are after is a piece of cake, just point and click.
The tricky thing in your case is that there are two relationships between the two tables. One relationship links EmpId to ID and the other links ManId to ID.
If, however, you want to learn SQL, then this shortcut will be a digression.
If you don't specify a join between the tables, a so called Cartesian product will be built, i.e., each record from one table will be paired with every record from the other table. If you have 7 records in one table and 10 in the other you will get 70 pairs (i.e. rows) before grouping. This explains why you are getting a count of 7 per manager name.
Besides joining the tables, I would suggest you to group on the manager id instead of the manager name. The manager id is known to be unique per manager, but not the name. This then requires you to either group on the name in addition, because the name is in the select list or to apply an aggregate function on the name. Each additional grouping slows down the query; therefore I prefer the aggregate function.
SELECT
COUNT(*) AS StaffCount,
FIRST(Manager.Name) AS ManagerName
FROM
Stafflink
INNER JOIN Employee AS Manager
ON StaffLink.ManId = Manager.Id
GROUP BY
StaffLink.ManId
I don't know if it makes a performance difference, but I prefer to group on StaffLink.ManId than on Employee.Id, since StaffLink is the main table here and Employee is just used as lookup table in this query.

How to correct "expression must have same data type as corresponding expression" error?

For example I have table department and employee
I want to find the names of the employees together with budget of department employees belong to
Inside employee table it contain employee name which is ename
department table it contain budget for department
The command that I used
SELECT ENAME FROM EMPLOYEE
UNION
SELECT BUDGET FROM DEPARTMENT
ORDER BY ENAME;
but I keep getting expression must have same data type as corresponding expression error
Can someone explain to me What is wrong with my concept and how to obtain the result .
As the error says. It looks as though ENAME is a string and BUDGET is a numeric.
It sounds like you want to return these two values in a query along the lines of:
SELECT ENAME, SUM(BUDGET)
FROM EMPLOYEE INNER JOIN BUDGET
ON EMPLOYEE.ID = BUDGET.ID
GROUP BY ENAME
Note I'm making assumptions as to your data types, randomly throwing an ID out there, and assuming you want to sum the data. Oh, and the platform. The SQL should be pretty standard I guess, but this is T-SQL.
I guess You're trying to union two tables which are having different datatype, and union requires datatype of both columns should be same.
http://technet.microsoft.com/en-us/library/ms180026.aspx
See the msdn says The data types must be compatible.