Need help fetching data from DB2 - sql

S.no
emp_id
emp_name
Dept
1
100
John
Sales
2
100
John
Accounts
3
200
Mike
Sales
4
300
Mark
Sales
5
300
Mark
Accounts
6
400
Tom
Sales
I need to pull all the emp_id who are linked ONLY to Sales Dept and ignore the ones that are in both Sales and Accounts. I am using DB2 z/os. Any suggestions would be helpful? Thanks in advance.

An anti-join will produce the result you want.
For example:
select s.*
from employee s
left join employee a on a.emp_id = s.emp_id and a.dept = 'Accounts'
where s.dept = 'Sales' and a.emp_id is null
For good performance you can try adding the index:
create index ix1 on employee (emp_id, dept);

Related

How to join/fill null values using second table while keeping other values intact?

How do I fill the null values in Table A using values from Table B while keeping all other columns/rows intact?
Table A
name
dept
job
jon
null
analyst
mary
null
supervisor
lucy
null
actuary
mark
retail
manager
cindy
retail
sales
Table B
name
dept
job
jon
hr
null
mary
hr
null
lucy
finance
null
attempts to use joins has incorrect results due to having to select which columns show in final table. ex:
SELECT a.name, b.dept, a.job
FROM table_a AS a
LEFT JOIN table_b AS b
ON a.name=b.name
will show
name
dept
job
jon
hr
analyst
mary
hr
supervisor
lucy
finance
actuary
mark
null
manager
cindy
null
sales
I've tried out different types of joins, but can't seem to figure it out. Thanks in advance!
Use COALESCE() to combine two values that could be null.
For example:
SELECT a.name,
coalesce(a.dept, b.dept) as dept,
coalesce(a.job, b.job) as job
FROM table_a AS a
LEFT JOIN table_b AS b
ON a.name=b.name

How to get Details of all Department(dept_id, name, dept_manager and total_employees) from tables(Department, Employee)?

Here are the details of the tables:
Employee :
emp_ID | Primary Key
emp_name | Varchar
emp_email | varchar <br>
emp_dept_id | Foreign Key
Departments :
dept_ID | Primary Key
dept_name | Varchar
emp_id | Foreign Key
Manager details are already there in the employee table.
I am using Oracle Database.
Employee:
emp_ID emp_name emp_email emp_dept_id
1 Cyrus abc#xyz.com 10
2 Andrew xyz#abc.com 20
3 Mark xyz#abc.com 10
4 Tony xyz#abc.com 10
5 Elvis xyz#abc.com 20
6 Rock xyz#abc.com 10
7 George xyz#abc.com 20
8 Mary xyz#abc.com 10
9 Thomas xyz#abc.com 20
10 Martin xyz#abc.com 10
Depqartments:
dept_id dept_name emp_id
10 Accounts 4
20 Development 9
These are the data in the tables. In Department table, emp_id(Foreign key) indicates the head/manager of the department .
You can try following query:
SELECT
D.DEPT_ID,
D.DEPT_NAME,
D.EMP_ID AS MANAGER_ID,
E.EMP_NAME AS MANAGER_NAME,
E.EMP_EMAIL AS MANAGER_EMAIL,
E.CNT AS "number of employees"
FROM
DEPARTMENT D
JOIN (
SELECT
EMP_ID,
EMP_NAME,
EMP_EMAIL,
EMP_DEPT_ID,
COUNT(1) OVER(
PARTITION BY EMP_DEPT_ID
) AS CNT
FROM
EMPLOYEE
) E ON ( E.DEPT_ID = D.EMP_DEPT_ID
AND E.EMP_ID = D.EMP_ID );
Cheers!!
This is pretty straightforward. You want to get the department details (1) and also include the employees associated with that department (2).
Get the department details:
SELECT <dept_col1>, <dept_col2>, ...
FROM Department
Get a summary of employees per department:
SELECT dept_ID, <aggregation> AS MyAgg
FROM department
GROUP BY dept_ID
Here you replace <aggregation> with whatever you're trying to find. In your case it would be COUNT(*).
Combine the two results. You want to join the data from (2) to (1). How are these two tables related? Here you write a LEFT JOIN to connect them on the PK/FK relationship:
SELECT
dept.<col1>, dept.<col2>, ...,
COALESCE(emp.MyAgg,0) AS MyAgg
FROM Department dept
LEFT JOIN (
SELECT dept_ID, <aggregation> AS MyAgg
FROM department
GROUP BY dept_ID
) emp ON dept.<FK> = emp.<PK>
Get the department manager's info by adding another LEFT JOIN:
SELECT
dept.<col1>, dept.<col2>, ...,
mgr.<col1>,
COALESCE(emp.MyAgg,0) AS MyAgg -- In case there are 0 employees
FROM Department dept
LEFT JOIN employee mgr ON dept.<FK> = mgr.<PK>
LEFT JOIN (
SELECT dept_ID, <aggregation> AS MyAgg
FROM department
GROUP BY dept_ID
) emp ON dept.<FK> = emp.<PK>
Give it a try and see how far you get. If you get stuck let me know.

How to get employees listed under their manager? SQL

I have a database:
Staff Name
1 Blake
2 Jake
Mgr Emp
2 6
2 8
3 5
4 7
Is it possible to search up all employees but list them under the manager?
Select all:
Staff Name Mgr
1 Blake null
2 Jake null
6 Scott 2
8 Jack 2
3 Clark null
5 Martin 3
4 Smith null
7 Scott 4
And is there a way to look up the team when a staff is searched?
Search: "Scott"
Returns:
Staff Name Mgr
2 Jake null
6 Scott 2
8 Jack 2
http://rextester.com/OAREI7219 is solution
CREATE TABLE Managers (
MgrID int ,
EmpID int
)
CREATE TABLE Staff (
EmpID int,
name nvarchar(50)
)
Query is ;
SELECT
s.EmpID AS Staff,
s.name AS Name,
m.MgrID
FROM Staff s LEFT JOIN Managers m ON s.EmpID = m.EmpID ;
GO
Assuming that you have:
a table "staff" with all the people in the company. For clarity I will rename the "Staff" column to "id".
a many to many table "staff_manager" to link employees with their managers. For clarity I will rename the "Mgr" column to "manager_id" and the "Emp" to "employee_id".
all tables named lowercase and plural.
You may do:
SELECT employees.id, employees.name, managers.id, managers.name
FROM staff as employees
LEFT JOIN employee_managers ON (employee_managers.employee_id = employees.id)
LEFT JOIN staff as managers ON (managers.id = employee_managers.manager_id)
for the second query you add a where clause to the above query:
WHERE managers.name = "Scott" OR employees.name = "Scott"
NOTE: If you may change the model of your database, I would suggest to
set a UNIQUE constrain on the employee_id of the staff_managers table,
so that one employee can have ONLY ONE manager.
To get All Employees with their managers. Try
Select staff.Id,Staff.name,managers.mgr
From staff left join managers on staf.id=managers.emp
To search about employee and get his team with the manager also. Try
— Search: 'scott'
Select staff.Id,Staff.name,managers.mgr
From staff left join managers on staf.id=managers.emp
Where managers.mgr =(select t.mgr from managers as t where t.emp='scott')
Union all
Select staff.Id,Staff.name,managers.mgr
From managers left join staff on staf.id=managers.mgr
Where managers.emp='scott'

Unable to make desired JOINS between multiple tables

I've got 3 tables
Plan:
plan_id emp_id duration
123 1010 30
456 1011 40
789 1012 60
PlanEmp:
plan_id emp_id
123 2131
456 3131
789 4131
Emp:
emp_id Name
1010 Andy
1011 Cole
1012 John
2131 Sam
3131 Kim
4131 Ray
Desired Summary Output:
plan_id Name duration
123 Andy 30
123 Sam 30
456 Cole 40
456 Kim 40
789 John 60
789 Ray 60
Query that I'm trying to modify to get the above result:
SELECT P.plan_id
,E.Name
,P.duration
FROM Plan P
LEFT JOIN Emp E
ON P.emp_id = E.emp_id
LEFT JOIN PlanEmp PE
ON P.plan_id = PE.plan_id
I'm unable to figure how to pull the Employee details using the PlanEmp table AND the Plan table to get the summary output.
This should work:
SELECT sub.plan_id, sub.emp_id, Emp.name, Plan.duration
FROM
(SELECT plan_id, emp_id
FROM Plan
UNION
SELECT plan_id, emp_id
FROM PlanEmp) sub
LEFT JOIN Emp
ON sub.emp_id = Emp.emp_id
LEFT JOIN Plan
ON sub.plan_id = Plan.plan_id
ORDER BY plan_id
Tested here: http://sqlfiddle.com/#!9/21ca79/4
Use the below script.
;With cte_1
As( select plan_id,emp_id
From plan
UNION
Select plan_id,emp_id
From plan_emp)
Select c.plan_id,e.Name,p.Duration
From cte_1 c
Join plan p on c.plan_id=p.plan_id
Join emp e on c. Emp_id=e.emp_id
I'm sure there's a logical explanation for this and since my reputation is not at the level to comment yet, but why is emp_id on both the Plan and PlanEmp tables? If you can normalize this, that would be a good idea to move emp_id off of the Plan table to the PlanEmp table.
Your table design is not following the needed Normalization practices. You should merge the table Plan and EmpPlan.
or
Your design should be (To normalize more):
Table: Plan
Plan_ID
Duration
Table: PlanEmp
Plan_ID
Emp_ID
Your existing structure can be queried with multiple ways but they may not efficient. Another way:
Select ISNULL(P.plan_id, PE.plan_id) Plan_ID, E.Name,
(Select Duration from #Plan pp Where pp.plan_id = ISNULL(P.plan_id, PE.plan_id)) as Duration
from Emp E
left Join #lan P on E.emp_id = P.emp_id
left Join PlanEmp PE on E.emp_id = PE.emp_id
Where P.emp_id IS NOT NULL or PE.emp_id is not null

sql query for getting data from two related tables

I have two tables, employee and inventory. One employee can have zero or more inventories.
I would like to list employee information along with at most one inventory information
and count of inventories belongs to one employee.
employee table
emp_num last_name first_name
-----------------------------------
100 john smith
101 mike pet
102 jes lyoid
inventory table
inv_num emp_num
---------------------------
12 100
13 100
15 100
30 102
desired Output
emp_num last_name invnum count(inv_num)
--------------------------------------------------------------------------
100 john 12 3
101 mike - 0
102 jes 30 1
What sql query can I use in this case?
Try this:
SELECT emp_num, last_name, MAX(inv_num) AS invnum, COUNT(inv_num) AS inv_count
FROM employee e LEFT OUTER JOIN inventory i ON e.emp_num = i.emp_num
GROUP BY e.emp_num, e.last_name
You could do something like this
Select E.Emp_Num,
e.Last_name,
MIN(Inv_Num) AS OldestInv,
COUNT(Inv_Num) AS TotalInv
FROM Employee E
LEFT OUTER JOIN Inventory I
(E.Emp_Num = I.Emp_Num)
GROUP BY E.Emp_Num, E.Last_Name
This will give you the minimum invoice number and the total count. The left outer join is the key
SELECT
e.emp_num,
e.last_name,
IFNULL(MAX(i.inv_num),'-') AS 'invnum',
COUNT(i.inv_num) AS 'count(inv_num)'
FROM
employee e LEFT JOIN inventory i
ON e.emp_num = i.emp_num
GROUP BY
e.emp_num, e.last_name