Query to Update Table using another table as information? - sql

I have two tables, Staff and Wages
Staff Contains
id, name, jobID, wage
1 Name1 2
2 Name2 4
3 Name3 1
4 Name4 2
Wages Contains
JobID, Wage
1 1500
2 800
3 1600
4 2000
(There are alot more columns in the actual one I have just took the top 4)
I am missing the wages inside the Staff table, and the wages I need in the staff table are the rates in the Wages table..
So I need a query which would make the Staff table look like:
id, name, jobID, wage
1 Name1 2 800
2 Name2 4 2000
3 Name3 1 1500
4 Name4 2 800
An example Query which I tried was:
UPDATE `Staff`
SET wage = (SELECT wage FROM `Wages`)
WHERE jobID = (Select jobId FROM `Wages`)
Thanks.

In MySQL,
UPDATE Staff a
INNER JOIN Wages b
ON a.jobID = b.JobID
SET a.wage = b.wage
In MSSQL,
UPDATE a
SET a.wage = b.wage
FROM Staff a
INNER JOIN Wages b
ON a.jobID = b.JobID
SOURCE

I would just leave the tables as they are (without the wage column in Staff), in their normalized state, and run this query anytime I need the full set of (denormalized) data:
SELECT s.id, s.name, s.jobID, w.wage
FROM Staff s
LEFT OUTER JOIN Wages w ON s.jobID = w.jobID

Related

SQL: Retrieve all records where has all joined

Sorry, couldn't think of a better title.
I have 3 tables in Oracle XE. An EMPLOYEE table a PROJECT table and a WORK_ON table. An EMPLOYEE can WORK_ON many PROJECTs. I am trying to get the employee name who is working on all the projects.
EMPLOYEE Table
Emp_ID EMP_Name
1 Esther
2 Peter
3 Joan
4 Roger
5 Liam
PROJECT Table
Project_ID
1
2
3
WROKS_ON Table
Emp_ID Project_ID
1 3
2 1
2 2
2 3
3 1
3 2
4 1
4 2
4 3
Given the fields my result should be Peter and Roger.
Started with the following, but got stuck:
SELECT EMP_NameLOYEE.E_NAME
FROM EMP_NameLOYEE INNER JOIN
(PROJECT INNER JOIN WROKS_ON ON PROJECT.Project_ID = WROKS_ON.Project_ID) ON
EMP_NameLOYEE.Emp_ID = WROKS_ON.Emp_ID
WHERE WROKS_ON.Project_ID In (SELECT DISTINCT Project_ID FROM PROJECT);
Obviously this retrieves all the names of the employees that are working on each project duplicated, but not exactly what I want.
You can leave the project table out of it.
SELECT e.emp_id, COUNT(project_id)
FROM employee e
INNER JOIN works_on wo ON wo.emp_id = e.emp_id
GROUP BY e.emp_id
HAVING COUNT( project_id ) = (SELECT COUNT(*) FROM project);
SQL Fiddle
You need to generate all combinations of employees and projects with a cross join and left join the works table and check for row counts for each e_name.
SELECT e.E_NAME
FROM EMPLOYEE e
CROSS JOIN PROJECT p
LEFT JOIN WORKS_ON w ON p.Project_ID = w.Project_ID and e.emp_id=w.emp_id
GROUP by e.E_NAME
HAVING COUNT(*)=COUNT(w.project_id)

SQL count 2 equal columns and select other columns

I have a two separate tables, one with vacancies, and one with applications to those vacancies. I want to select a new table which selects from the vacancies table with a number of other columns from that table, and another column that calculates how many applications there are for those vacancies. So my vacancy table looks like this:
ID Active StartDate JobID JobTypeID HoursPerWeek
1 1 2017-02-28 2 CE 0
2 1 2017-02-15 4 CE 40
3 1 2017-02-14 1 CE 40
4 1 2017-02-28 1 CE 48
My applications table looks like this:
ID VacancyID Forename Surname EmailAddress TelephoneNumber
1 1 John Smith jsmith#gmail.com 447777777777
2 2 John Smith jsmith#gmail.com 447748772641
3 2 John Smith jsmith#gmail.com 447777777777
4 2 John Smith jsmith#gmail.com 447700123456
5 4 John Smith jsmith#gmail.com 447400123569
6 4 John Smith jsmith#gmail.com 447400126547
7 4 John Smith jsmith#gmail.com 447555123654
I want a table that looks like this:
ID Active StartDate JobID HoursPerWeek NumberOfApplicants
1 1 2017-02-28 2 0 1
2 1 2017-02-15 4 40 3
3 1 2017-02-14 1 40 0
4 1 2017-02-28 1 48 3
How can I select that table using joins and count the number of applicants where the VacancyID is equal to the ID of the first vacancy table? I have tried:
select Vacancy.ID, VacancyID, count(*) as NumberOfApplications from VacancyApplication
join Vacancy on Vacancy.ID=VacancyID
group by VacancyID, Vacancy.ID
This obviously doesn't select all the other columns and it also does not select ID 3 because there are 0 applications for that - I want ID 3 to be there with a value of 0 as well as all the other columns. How do I do this? I've tried various forms of grouping and selecting but I'm quite new to SQL so I'm not really sure how this can be done.
Use RIGHT JOIN instead of INNER JOIN and count the vacancyid column from vacancyapplication table. For the non matching records you will get count as 0
SELECT v.id, v.Active, v.StartDate, v.JobID, v.HoursPerWeek
Count(va.vacancyid) AS NumberOfApplications
FROM vacancyapplication va
RIGHT JOIN vacancy v
ON v.id = va.vacancyid
GROUP BY v.id, v.Active, v.StartDate, v.JobID, v.HoursPerWeek
Start using Alias names, it makes the query more readable
Hoping, i understood your problem correctly. Please try below query
select Vacancy.ID, VacancyID, count(*) as NumberOfApplications from VacancyApplication
left join Vacancy on Vacancy.ID=VacancyID
group by VacancyID, Vacancy.ID
You can use count as a window function using the OVER clause, thus eliminating he need for group by:
SELECT v.ID,
v.Active,
v.StartDate,
v.JobID,
v.JobTypeID,
COUNT(va.ID) OVER(PARTITION BY v.ID) HoursPerWeek
FROM Vacancy v
LEFT JOIN vacancyapplication va ON(v.ID = va.VacancyID)
Use left join and table aliases:
select v.ID, count(va.VacancyID) as NumberOfApplications
from Vacancy v join
VacancyApplication va
on v.ID = va.VacancyID
group by v.ID;
You seem to want all the columns. You could include them in the group by. However, a correlated subquery or outer apply is simpler:
select v.*, va.cnt
from vacancy v outer apply
(select count(*) as cnt
from VacancyApplication va
where v.ID = va.VacancyID
) va;
This is probably more efficient anyway, especially if you have an index on VacancyApplication(VacancyID).

How to join multiple tables and retrieve an aggregate

I have 3 tables and need to retrieve each EmployeeID, their Name, and their total WorkTime. My table structure is as follows:
DEPT TABLE
ID DEPTNAME DESIGNATION
1 MG MANAGER
2 AN ANALYTICS
3 DV DEVELOPER
4 PM PM
WORK TABLE
EMPID WORKTIME ID(FK TO TABLE DEPT) DATE
1 8 1 09/15/2014
2 7 2 09/15/2014
1 6 1 09/16/2014
2 8 2 09/16/2014
EMP TABLE
EMPID NAME
1 SK
2 TK
3 MK
4 CK
I want all the Employee names with ID and the total working time, as below:
EMPID NAME WORKTIME NOOFDATESWORKS
1 SK 14(8+6) 2
2 TK 15(7+8) 2
3 MK 0
4 CK 0
*please note: employees can work for multiple departments
SELECT E.EmpID,
E.Name,
W.TotalWorkTime
FROM Emp E
LEFT JOIN ( SELECT EMID, SUM(WorkTime) TotalWorkTime
FROM Work
GROUP BY EMID) W
ON E.EmpID =W.EMID
By the way, shouldn't the department Id be on the Emp table rather than the Work table?, as it is it doesn't make much sense to me

Oracle SQL No Data in series

I have a query result that is almost perfect except for the fact that in the result I don't always have a complete series in my muli-series data that I am trying to eventually show in a report and chart.
NAME MONTH COST
----------------------------------------
name1 2 100
name1 3 80
name2 1 60
name3 2 30
----------------------------------------
Here is query:
select Name, month, count(*) as cost
from table1
group by name, month
order by month, name
What I have here isn't one simple set of data, but a series of data. For each month, I have a set of users and sales.
I can fix this on my application side by doing a few loops and getting the distinct values for Name and Month.
I'd like to learn how to create my Oracle query to get a result set that looks something like this
NAME MONTH COST
----------------------------------------
name1 1 0
name1 2 100
name1 3 80
name2 1 60
name2 2 0
name2 3 0
name3 1 0
name3 2 30
name3 3 0
----------------------------------------
You can do this with a cross join and then a left outer jon:
select n.name, m.month, coalesce(t.cost, 0) as cost
from (select distinct name from table t) n cross join
(select distinct month from table t) m left join
table t
on t.name = n.name and t.month = m.month
order by n.name, m.month;

How to count linked entries in another table with a specific value

Let's say I have two tables. A students table and an observations table. If the students table looks like:
Id Student Grade
1 Alex 3
2 Barney 3
3 Cara 4
4 Diana 4
And the observations table looks like:
Id Student_Id Observation_Type
1 1 A
2 1 B
3 3 A
4 2 A
5 4 B
6 3 A
7 2 B
8 4 B
9 1 A
Basically, the result I'd like from the query would be the following:
Student Grade Observation_A_Count
Alex 3 2
Barney 3 1
Cara 4 2
Diana 4 0
In other words, I'd like to gather data for each student from the students table and for each student count the number of A observations from the observations table and tack that onto the other information. How do I go about doing this?
This is a simple join and aggregate:
select
a.Student,
a.Grade,
count(b.Id) as Observation_A_Count
from
Student a left join
Observations b on a.Id = b.Student_Id
group by
a.Student,
a.Grade
order by
1
Or, you can use a correlated subquery:
select
a.Student,
a.Grade,
(select count(*) from observations x where x.Student_Id = a.Id) as Observation_A_Count
from
Student a
order by
a.Student
You can join the table with a specific condition, by doing this you can have a field for Observation_B_Count and Observation_C_Count, etc.
SELECT Student.Student, Student.Grade, COUNT(Observation_Type.*) AS Observation_A_Count
FROM Student
LEFT JOIN Observations ON Observations.Student_ID = Student.Student_ID AND Observations.Observation_Type = 'A'
GROUP BY Student.Student, Student.Grade