Displaying the same fields AS different names from the same table -Access 2010 - sql

I have EmployeeName; it is from the Employee table. The Employee table holds ALL Employees in the organization and the Employee table references the primary key of the Position table, which holds the different position names. So this is how I'm differentiating between employees in the Employee table; each record in the Employee table has a PosNo which references the Position table(worker = Pos1, manager = Pos2, etc...) So for simplicity's sake, a record in the employee table would be similar to: EmployeeName, EmployeeAddress, DeptNo, PosNo
Here's the problem: Certain positions are under other positions. There are workers in the Employee table and there are managers in the Employee table. I'm wanting to make a table that lists all workers and their managers. For example, the table would have two fields: EmployeeName, ManagerName.
The Employee table is broken down into a generalization hierarchy. The Salary and Hourly tables branch out from Employee table. Then, from the Salary table, another table branches out called Manager(which I call ProgramSupervisor; it has a unique field). Workers are part of the Hourly table though. Managers(ProgramSupervisor) and Workers(Hourly) are related to each other through the ISL table. The Manager is the head of the ISL and therefore ISL has a ManagerNo as one of its fields. Workers(Hourly), however, work in the ISL and therefore have ISLNo as a field in their table, the Hourly table.
So, I'm trying to find a way to relate all of these table as make a table with two fields, workers and managers, in which the workers belong to managers through the ISL table. Would I use a nested query of some sort? I'll post my code so far, which is absolutely not correct (probably no even on the right track) and I'll post my ERD so you can get a better picture of how the tables relate.
SELECT EmpLastName + ', ' + EmpFirstName as ProgSupName,
EmpLastName + ', ' + EmpFirstName as EmpName
FROM Employee, Salary, ProgramSupervisor, ISL, Hourly
WHERE Employee.EmpNo = Salary.EmpNo
AND Salary.EmpNo = ProgramSupervisor.EmpNo
AND ProgramSupervisor.EmpNo = ISL.ProgramSupervisor_EmpNo
AND ISL.ISLNo = Hourly.ISLNo
AND Hourly.EmpNo = Employee.EmpNo
ERD

In its simplest form you can distill the Employee-Supervisor relationship down to three tables:
[Employee]
EmpNo EmpFirstName EmpLastName
----- ------------ -----------
1 Montgomery Burns
2 Homer Simpson
[Hourly]
EmpNo ISLNo
----- -----
2 1
[ISL]
ISLNo ProgramSupervisor_EmpNo ISLName
----- ----------------------- -------------------------
1 1 Springfield Nuclear Plant
If you put them together in a query that looks like this
it produces results like this:
Employee_LastName Employee_FirstName ISLName Supervisor_LastName Supervisor_FirstName
----------------- ------------------ ------------------------- ------------------- --------------------
Simpson Homer Springfield Nuclear Plant Burns Montgomery
"But wait a minute!" I hear you say, "There are four tables in that query. Where did the [Supervisor] table come from?"
That is just another instance of the [Employee] table that uses [Supervisor] as its alias. A table can appear in a query more than once provided that we use aliases to specify the instance to which we are referring when we talk about [EmpLastName], [EmpFirstName], etc..
The SQL for the above query shows the second instance Employee AS Supervisor on the second-last line:
SELECT
Employee.EmpLastName AS Employee_LastName,
Employee.EmpFirstName AS Employee_FirstName,
ISL.ISLName,
Supervisor.EmpLastName AS Supervisor_LastName,
Supervisor.EmpFirstName AS Supervisor_FirstName
FROM
(
Employee
INNER JOIN
(
Hourly
INNER JOIN
ISL
ON Hourly.ISLNo = ISL.ISLNo
)
ON Employee.EmpNo = Hourly.EmpNo
)
INNER JOIN
Employee AS Supervisor
ON ISL.ProgramSupervisor_EmpNo = Supervisor.EmpNo

Related

On Statement Self Join

I am having trouble wrapping my head around the on statement when doing a self-join. Let's say we have the following table:
employeeid
name
managerid
salary
1
Mike
3
35000
2
Rob
1
45000
3
Todd
NULL
25000
4
Ben
1
55000
5
Sam
1
65000
I want to perform a self join to return the employee name and their manager's name.
When I perform the following self join I get an incorrect result:
SELECT E.name as Employee,M.name as Manager
FROM tblEmployees E
LEFT JOIN tblEmployees M
ON E.Employeeid=M.managerid
However, when I reverse the columns on the on statement using the query below:
SELECT E.name as Employee,M.name as Manager
FROM tblEmployees E
LEFT JOIN tblEmployees M
ON E.managerid=M.Employeeid
I get the correct answer.
Why? How do I know which columns to select in an on statement?
Here's my explanation:
The table you have is structured with each row representing an employee in the company.
You are interested in determining who is each employee's manager.
You are able to find that by joining the table on itself where the lookup values are the manager ids (managerid) and the reference column are the employee ids (employeeid).
The first query is wrong because the employeeid column is being used for the lookup values and the managerid column is being used for reference.
To get the manager of each employee you need to look use the managerid column as the lookup column and the employeeid column as the reference column.
Hope that's not too confusing!

What happens if one query contains duplicate joins?

I have an application filter which can generate duplicate SQL queries to the result SQL like:
select * from articles
inner join users on articles.users_id = users.id
inner join users on articles.users_id = users.id
where users.name like %xxx%
The question is if a database is able to handle these duplicates or not. What happened in the database if this query comes inside? If I should remove it from the result SQL or if I can leave it as is.
This is a self join.
A self join is a regular join, but the table is joined with itself.
Example
SELECT
A.Id,
A.FullName,
A.ManagerId,
B.FullName as ManagerName
FROM Employees A
JOIN Employees B
ON A.ManagerId = B.Id
A and B are different table aliases for the same table.
The self join, as its name implies, joins a table to itself. To use a self join, the table must contain a column (call it X) that acts as the primary key and a different column (call it Y) that stores values that can be matched up with the values in Column X. The values of Columns X and Y do not have to be the same for any given row, and the value in Column Y may even be null.
Let’s take a look at an example. Consider the table Employees:
Id
FullName
Salary
ManagerId
1
John Smith
10000
3
2
Jane Anderson
12000
3
3
Tom Lanon
15000
4
4
Anne Connor
20000
5
Jeremy York
9000
1
Each employee has his/her own Id, which is our “Column X.” For a given employee (i.e., row), the column ManagerId contains the Id of his or her manager; this is our “Column Y.” If we trace the employee-manager pairs in this table using these columns:
The manager of the employee John Smith is the employee with Id 3,
i.e., Tom Lanon.
The manager of the employee Jane Anderson is the employee with Id 3,
i.e., Tom Lanon.
The manager of the employee Tom Lanon is the employee with Id 4,
i.e., Anne Connor.
The employee Anne Connor does not have a manager; her ManagerId is
null.
The manager of the employee Jeremy York is the employee with Id 1,
i.e., John Smith.
This type of table structure is very common in hierarchies. Now, to show the name of the manager for each employee in the same row, we can run the following query:
SELECT
employee.Id,
employee.FullName,
employee.ManagerId,
manager.FullName as ManagerName
FROM Employees employee
JOIN Employees manager
ON employee.ManagerId = manager.Id
which returns the following result:
Id
FullName
ManagerId
ManagerName
1
John Smith
3
Tom Lanon
2
Jane Anderson
3
Tom Lanon
3
Tom Lanon
4
Anne Connor
5
Jeremy York
1
John Smith
The query selects the columns Id, FullName, and ManagerId from the table aliased employee. It also selects the FullName column of the table aliased manager and designates this column as ManagerName. As a result, every employee who has a manager is output along with his/her manager’s ID and name.
In this query, the Employees table is joined with itself and has two different roles:
Role 1: It stores the employee data (alias employee).
Role 2: It stores the manager data (alias manager).
By doing so, we are essentially considering the two copies of the Employees table as if they are two distinct tables, one for the employees and another for the managers.
You can find more about the concept of the self join in our article "An illustrated guide to the SQL self join".

Aggregate one table twice on different level

I am a little bit a newbie in SQL and am struggling with a seemingly easy task.
Let's see the data:
FirstName LastName ID DepartmentNumber ManagerID
Aliana Abramova 1111111111 4 4610226861
Boriana Borova 2222222222 4 4610226861
Cali Moldovanska 3333333333 4 4610226861
Anelia Simeonova 4009016246 1 4009016246
Maria Tacheva 4206174562 3 4206174562
This is an employee table. What I am trying to do is to extract these employees that are managers (ID = ManagerID) but only these out of them that work in a department that have more than one employees (so only these that have a count of ID grouped by DepartmentNumber >0)
I can do this tasks separately:
Select FirstName, LastName, ID
from Employee
where ID = ManagerID;
Select count(ID)
from Employee
group by DepartmentNumber;
It is hard for me though, to somehow merge this knowledge into one query and combined the data so that I know which are these IDs that belong to employees that are both managers and in their department work more than 1 person.
I have done similar tasks but when it comes to merging 1-2-3 tables grouped on different levels (and merged by different keys) I get somehow confused. Probably I need to make an interim select statement but now sure how.
You can use EXISTS:
SELECT *
FROM dbo.YourTable A
WHERE EXISTS(SELECT 1 FROM dbo.YourTable
WHERE DepartmentNumber = A.DepartmentNumber
GROUP BY DepartmentNumber
HAVING COUNT(*) > 1)
AND ID = ManagerID;

UPDATE query that fixes orphaned records

I have an Access database that has two tables that are related by PK/FK. Unfortunately, the database tables have allowed for duplicate/redundant records and has made the database a bit screwy. I am trying to figure out a SQL statement that will fix the problem.
To better explain the problem and goal, I have created example tables to use as reference:
alt text http://img38.imageshack.us/img38/9243/514201074110am.png
You'll notice there are two tables, a Student table and a TestScore table where StudentID is the PK/FK.
The Student table contains duplicate records for students John, Sally, Tommy, and Suzy. In other words the John's with StudentID's 1 and 5 are the same person, Sally 2 and 6 are the same person, and so on.
The TestScore table relates test scores with a student.
Ignoring how/why the Student table allowed duplicates, etc - The goal I'm trying to accomplish is to update the TestScore table so that it replaces the StudentID's that have been disabled with the corresponding enabled StudentID. So, all StudentID's = 1 (John) will be updated to 5; all StudentID's = 2 (Sally) will be updated to 6, and so on. Here's the resultant TestScore table that I'm shooting for (Notice there is no longer any reference to the disabled StudentID's 1-4):
alt text http://img163.imageshack.us/img163/1954/514201091121am.png
Can you think of a query (compatible with MS Access's JET Engine) that can accomplish this goal? Or, maybe, you can offer some tips/perspectives that will point me in the right direction.
Thanks.
The only way to do this is through a series of queries and temporary tables.
First, I would create the following Make Table query that you would use to create a mapping of the bad StudentID to correct StudentID.
Select S1.StudentId As NewStudentId, S2.StudentId As OldStudentId
Into zzStudentMap
From Student As S1
Inner Join Student As S2
On S2.Name = S1.Name
Where S1.Disabled = False
And S2.StudentId <> S1.StudentId
And S2.Disabled = True
Next, you would use that temporary table to update the TestScore table with the correct StudentID.
Update TestScore
Inner Join zzStudentMap
On zzStudentMap.OldStudentId = TestScore.StudentId
Set StudentId = zzStudentMap.NewStudentId
The most common technique to identify duplicates in a table is to group by the fields that represent duplicate records:
ID FIRST_NAME LAST_NAME
1 Brian Smith
3 George Smith
25 Brian Smith
In this case we want to remove one of the Brian Smith Records, or in your case, update the ID field so they both have the value of 25 or 1 (completely arbitrary which one to use).
SELECT min(id)
FROM example
GROUP BY first_name, last_name
Using min on ID will return:
ID FIRST_NAME LAST_NAME
1 Brian Smith
3 George Smith
If you use max you would get
ID FIRST_NAME LAST_NAME
25 Brian Smith
3 George Smith
I usually use this technique to delete the duplicates, not update them:
DELETE FROM example
WHERE ID NOT IN (SELECT MAX (ID)
FROM example
GROUP BY first_name, last_name)

SQL query to return data from two separate rows in a table joined to a master table

I have a TWO tables of data with following fields
table1=(ITTAG,ITCODE,ITDESC,SUPcode)
table2=(ACCODE,ACNAME,ROUTE,SALMAN)
This is my customer master table that contains my customer data such as customer code, customer name and so on...
Every Route has a supervisor (table1=supcode) and I need to know the supervisor name in my table which both supervisor name and code exist in one table.
table1 has contain all names separated by ITTAG. For example, supervisor's name has ITTAG='K'; also salesman's name has ITTAG='S'.
ITTAG ITCODE ITDESC SUPCODE
------ ------ ------ -------
S JT JOHN TOMAS TF
K WK VIKI KOO NULL
Now this is the result which I want
ACCODE ACNAME ROUTE SALEMANNAME SUPERVISORNAME
------- ------ ------ ------------ ---------------
IMC1010 ABC HOTEL 01 JOHN TOMAS VIKI KOO
I hope this this information is sufficient to get the query..
Your data structure is either not clear or incomplete. It would help if you showed the actual example data for Table1 too, but there would be trouble.
SELECT t2.ACCODE, t2.ACNAME, t2.ROUTE, a1.ITDESC AS Salesman, a2.ITDESC AS Supervisor
FROM table1 AS t1
JOIN table2 AS a1 ON t1.SALMAN = a1.ITCODE
JOIN table2 AS a2 ON t1.?????? = a2.SUPCODE
It is not clear whether I've managed the join between Table1 and Table2 for the salesman information correctly; it is plausible, but the join for the supervisor should be similar, and yet there isn't a way to make that work. Hence the '??????' in the query.
The basic technique for joining twice to a single table is to cite it twice with different aliases, as shown. I usually use one letter or a letter and a digit for the aliases, as shown.