Update only rows that does not match rows from another table - sql

I have 3 tables:
1) tblPerson
id pin name dept_id
---|-----------|------------|------------|
1 | 123 | Lisa | 100 |
2 | 234 | Rob | 200 |
2) tblDepartment
id dept_name
-----|-----------|
100 | IT |
200 | HR |
3) tblMaster
id emplid name m_dept
---|-----------|------------|------------|
1 | 123 | Lisa | IT |
2 | 234 | Rob | HR |
• tblDepartment gets its rows from existing departments present in tblMaster
• in tblPerson, dept_id is a foreign key from tblDepartment
I am trying to create a query that will update the dept_id in tblPerson for all rows where the m_dept does not match the dept_name of the dept_id linked to a person.
So for example, if in tblMaster, I change 'IT' under m_dept from row 1 to 'HR', running the query will change the dept_id of row 1 in tblPerson to '200'
SQL Query:
UPDATE [dbo].[tblPerson]
SET dept_id = d.id
FROM [dbo].[tblMaster] m
INNER JOIN [dbo].[tblPerson] p
ON p.pin = m.emplid
INNER JOIN [dbo].[tblDepartment] d
ON d.dept = m.m_dept
the query above will update all rows..when i try to add:
WHERE d.dept != m.m_dept
and I change the m_dept 'IT' to 'HR' of row 1 in tblMaster ..it does not update anything
need help please ;m;

You are currently using both d.dept = m.m_dept (in the JOIN condition) and d.dept != m.m_dept in the WHERE, so of course you are updating no rows.
You either use a EXISTS or NOT EXISTS, or another JOIN:
UPDATE P
SET P.dept_id = D1.id
FROM dbo.tblPerson P
INNER JOIN dbo.tblMaster M
ON P.pin = M.emplid
INNER JOIN dbo.tblDepartment D1
ON D1.dept_name = M.m_dept
INNER JOIN dbo.tblDepartment D2
ON P.dept_id = D2.id
WHERE D1.dept_name <> D2.dept_name
;

Related

SQL Query, I need 1 line per person with lowest Id of two columns

SELECT
Mem.MemberID, Mem.LastName + ', ' + Mem.FirstName AS Name,
MD.DiagnosisID,
Diag.DiagnosisDescription,
DC.DiagnosisCategoryID, DC.CategoryDescription, DC.CategoryScore
FROM
Member AS Mem
LEFT OUTER JOIN
MemberDiagnosis AS MD ON Mem.MemberID = MD.MemberID
LEFT OUTER JOIN
Diagnosis AS Diag ON MD.DiagnosisID = Diag.DiagnosisID
LEFT OUTER JOIN
DiagnosisCategoryMap AS Map ON Map.DiagnosisID = Diag.DiagnosisID
LEFT OUTER JOIN
DiagnosisCategory AS DC ON DC.DiagnosisCategoryID = Map.DiagnosisCategoryID
ORDER BY
Name ASC
I have this query, which returns the following results:
ID | Name | D.ID | D.Desc | C.ID | C. Desc | C.Score
----+---------------+------+----------------+------+-------------+----------
2 | Smith, Jack | NULL | NULL | NULL | NULL | NULL
1 | Smith, John | 2 | Test Diagnosis | 2 | Category B | 20
1 | Smith, John | 4 | Test Diagnosis | 3 | Category C | 30
3 | Smyth, Will | 3 | Test Diagnosis | 3 | Category C | 30
3 | Smyth, Will | 4 | Test Diagnosis | 3 | Category C | 30
With in that query and result set, how can I go about returning 1 line per person with;
The lowest Diagnosis ID and it's desc.
The lowest Category ID with desc and score.
In stead of null category, return Category ID 1 and its desc and score.
Try the following query:
SELECT T1.*,Diag2.DiagnosisDescription, DC2.CategoryDescription, DC2.CategoryScore
FROM (SELECT DISTINCT
Mem.MemberID, Mem.LastName + ', ' + Mem.FirstName AS Name,
MIN(MD.DiagnosisID) OVER(PARTITION BY Mem.MemberID) AS DiagnosisID,
MIN(ISNULL(DC.DiagnosisCategoryID,1)) OVER(PARTITION BY Mem.MemberID) AS DiagnosisCategoryID
FROM
Member AS Mem
LEFT OUTER JOIN
MemberDiagnosis AS MD ON Mem.MemberID = MD.MemberID
LEFT OUTER JOIN
Diagnosis AS Diag ON MD.DiagnosisID = Diag.DiagnosisID
LEFT OUTER JOIN
DiagnosisCategoryMap AS Map ON Map.DiagnosisID = Diag.DiagnosisID
LEFT OUTER JOIN
DiagnosisCategory AS DC ON ISNULL(DC.DiagnosisCategoryID,1) = ISNULL(Map.DiagnosisCategoryID,1) ) AS T1
LEFT JOIN Diagnosis AS Diag2 ON T1.DiagnosisID = Diag2.DiagnosisID
LEFT JOIN DiagnosisCategory AS DC2 ON T1.DiagnosisCategoryID = DC2.DiagnosisCategoryID
ORDER BY T1.NAME

Check the count of column value is equal to one based on condition in sql server

I have two tables
Student
StudentId | StudentName
---------- | --------------
1 | John
2 | Susan
3 | Andy
4 | Joe
Department
StudentId | DepartmentId
---------- | ------------
1 | 123
1 | 234
2 | 123
2 | 456
3 | 123
4 | 456
Each student can be in multiple departments but I have to find those students which are only in one department like student 3 and 4
Any help?
Use GROUP BY and HAVING
SELECT s.StudentId,s.StudentName
FROM Department d
JOIN Student s ON s.StudentId=d.StudentId
GROUP BY s.StudentId,s.StudentName
HAVING COUNT(d.DepartmentId)=1
And if you also want to show students which not in Department table
SELECT s.StudentId,s.StudentName
FROM Department d
RIGHT JOIN Student s ON s.StudentId=d.StudentId
GROUP BY s.StudentId,s.StudentName
HAVING COUNT(d.DepartmentId)<=1
Variant with LEFT JOIN
SELECT s.StudentId,s.StudentName
FROM Student s
LEFT JOIN Department d ON s.StudentId=d.StudentId
GROUP BY s.StudentId,s.StudentName
HAVING COUNT(d.DepartmentId)<=1
Try this,
SELECT st.StudentId, St.StudentName
FROM student st
JOIN Department dep ON dep.StudentId = st.StudentId
GROUP BY st.StudentId
HAVING COUNT(dep.DepartmentId) = 1;
You can use IN with department table group by StudentId alongwith having count(Student_Id) = 1 in sub-query as below.
SELECT *
FROM student s
WHERE s.StudentId IN (
SELECT d.StudentId
FROM Department d
GROUP BY d.StudentId
HAVING count(d.DepartmentId) = 1
);
Result:
+-----------+-------------+
| studentid | studentname |
+-----------+-------------+
| 3 | Andy |
| 4 | Joe |
+-----------+-------------+
DEMO
Simply join them & aggregate them by Group by clause with having.. count() function
SELECT s.StudentId, s.StudentName
FROM student s
JOIN Department d ON d.StudentId = s.StudentId
GROUP BY s.StudentId, s.StudentName
HAVING COUNT(d.DepartmentId) = 1;
Result :
studentid studentname
3 Andy
4 Joe
Another approach is to eliminate the students having multiple departments at the beginning by using a cte table, then use the table with IN keyword like:
with cte as (
select StudentId
from Department
group by StudentId
having count(StudentId)=1
)
select *
from Students
where StudentId in (select StudentId from cte)

Join tables by child table id without inner select

I have two tables (owner and employee) and a mapping table (owner_employee)
I need a select statement which gets all owner employees by employee_id without using inner selects
Example:
SELECT * FROM employee e
[...Joins here...]
WHERE e.id = 1
should return
owner | employee
1 | 1
1 | 2
Owner table
id | title
----------
1 | a
2 | b
3 | c
Employee table
id | title
----------
1 | a
2 | a
3 | b
4 | c
Owner_Employee
id_owner | id_employee
----------------------
1 | 1
1 | 2
2 | 3
3 | 4
Working implementation of inner select here (probably working, because I rewrote it from original example)
SELECT *
FROM owner_employee oe
JOIN owner o ON o.id = oe.id_owner
JOIN employee e ON e.id = oe.id_employee
WHERE o.id in
(SELECT id_owner
FROM owner_employee oe
WHERE oe.id_employee in (1))
perhaps like this:
SELECT DISTINCT oe.*,o.*,e.*
FROM owner_employee AS z
JOIN owner_employee oe on oe.id_owner = z.id_owner
JOIN owner o ON o.id = oe.id_owner
JOIN employee e ON e.id = oe.id_employee
WHERE z.id_employee in (1);
The query code you give (which does not return what your text asks for) is the same as
SELECT *
FROM owner_employee oe
JOIN owner o ON o.id = oe.id_owner
JOIN employee e ON e.id = oe.id_employee
WHERE oe.id_employee = 1
But what your text asks for, "all owner employees by employee_id" apparently doesn't make sense. Becuase from your data one owner can have more than one id_employee.
If you want "all id_owners and their id_employees":
SELECT * FROM owner_employee
IF you want "id_employees of all owners":
SELECT id_employee FROM owner_employee
Or maybe you want "all owners, each by one of their employee ids"?

Return name of the employee who having top salary with join

here is the situation. I have two tables, one is table Tbl_employ, second is tbl_details.
Tbl_employ
----------
id | name
1 | Ravi
2 | ram
3 | sham
4 | john
Tbl_details
-----------
id | salary | emp_id
1 | 500 | 1
2 | 200 | 2
3 | 400 | 3
4 | 501 | 4
I want to return the name of the employee who has top salary in tbl_detail.
What will be the join query for this condition?
Please suggest. Thanks in advance.
Perhaps:
SELECT TOP(1) name
FROM Tbl_employ e INNER JOIN Tbl_details d ON e.id = d.emp_id
ORDER BY d.salary DESC;
Essentially, this joins the two tables on the key fields (id and emp_id), returning only a single result (TOP(1)) that is the maximum salary row (ORDER BY d.salary DESC).
I appreciate the answer of #Max Vernon.
You can also do it by another way. Please try this
select t.name from (
select Distinct top 1 salary ,name
from Tbl_employ as E
left outer join Tbl_details as D on D.empid=E.id
order by salary desc
) as t
you can check it here SQL Fiddle

Oracle Query design

I have two tables joining with left outer join
Employee
Employeed_Id Employee_Name Location_id
1 David 1
2 Andrew 2
3 Mike 3
4 steve 4
Employee_profile
profile_id profile_name location_id profile_location
1 manager 1 NYC
2 accountant 2 Jersey
3 engineer 1 Mexico
4 trainer 3 Boston
This is the common query I have to retrieve the all employees based on location.here profile_location is unique.
Problem is, in some part of the application profile_location is not required. So Outer join between above tables is not required.
How to develop a query, so it should function normally in case of profile_location not have input value with outer join.
Below is my Query:
select e.Employee_Name
from Employee e,
Employee_profile ep
where e.location_id (+) = ep.location_id
and ep.profile_location='xxxxx'
If you want to return those records that match your passed in profile_location but also want to return all records when the location does not exist, then you can use something like this:
select distinct e."Employee_Name"
from Employee e
left join Employee_profile ep
on e."Location_id" = ep."location_id"
where ep."profile_location" = 'xxx'
or not exists (select ep1."profile_location"
from Employee_profile ep1
where ep1."profile_location" = 'xxx')
See SQL Fiddle with Demo
If you pass in a value that does not exist like 'xxx' the result is:
| EMPLOYEE_NAME |
-----------------
| David |
| Andrew |
| steve |
| Mike |
If you pass in 'NYC' the result is:
| EMPLOYEE_NAME |
-----------------
| David |
select e.Employee_Name
from Employee e,
Employee_profile ep
where e.location_id (+) = ep.location_id
and (ep.profile_location='xxxxx'
Or ep.profile_location is null)