sql SELECT query - which merges 2 identical tables? - sql

So I have 2 tables. Employee and Draft_Employee. They are identical, except that properties in Draft_Employee allow nulls.
The reason for the 2 identical tables, is that the draft_Employee is a table used for an import procedure - it is a tempoary container. We don't want the data messed up with the production employees.
Now, when a employee has to be imported, the system has to check if the employee already exists in the database.
First it see's if it can find an employee in Employee table with the same EmpID.
If found, it will look at employee in Draft_Employee and find the properties which are NULL or EMPTY. It will then take the value for the same field in Employee table and put it into the empty or NULL fields in draft_Employee
empID name something1 something2 | empID name something1 something2
----- ---- ---------- ---------- | ---- ---- ---------- -----------
1 Casper blahblah blahblah2 | 2 Michael NULL text2fs
2 Michael txttxt |
Right is Employee and left is Draft_Employee.
I want an sql query that produces
empID name something1 something2
----- ---- ---------- ----------
2 Michael txttxt text2fs
The closest I have come, is with LEFT OUTER JOIN but it gives me data from both tables
EDIT: My query. I did not use it before, because the spelling is danish.
SELECT * FROM Kladde_Ressource
LEFT OUTER JOIN Ressource
ON Ressource.RessourceID = Kladde_Ressource.RessourceID
WHERE Kladde_Ressource.EAN = ''
OR Kladde_Ressource.navnLang = ''
OR Kladde_Ressource.navnKort = ''
etc...

I don't entirely grasp your requirement so I am basing my query on the data and required result you've posted.
As to get the results merged into one result set
use COALESCE to get the first non-NULL value from both tables.
use an INNER JOIN to remove the non-matching rows.
Statement
SELECT e.empID
, COALESCE(e.name, de.name) AS name
, COALESCE(e.something1, de.something1) AS something1
, COALESCE(e.something2, de.something2) AS something2
FROM employee e
INNER JOIN draft_employee de ON de.empID = e.empID

This should do the trick:
SELECT Employee.empId,
ISNULL(Employee.name, Draft_Employee.name) AS name,
ISNULL(Employee.something1, Draft_Employee.something1) AS something1,
ISNULL(Employee.something2, Draft_Employee.something2) AS something2
FROM Employee LEFT OUTER JOIN
Draft_Employee ON Employee.empID = Draft_Employee.EmpId

Use the coalesce function to get the first non-null value:
select
e.empID,
coalesce(d.name, e.name),
coalesce(d.something1, e.something1),
coalesce(d.something2, e.something2)
from
Employee e
inner join Draft_Employee d on d.empID = e.empID

How about using UNION and GROUP BY:
SELECT empID, name, MAX(something1) AS something1, MAX(something2) AS something2
FROM (
SELECT empID, name, something1, something2 FROM Employee WHERE empID = 2
UNION
SELECT empID, name, something1, something2 FROM draft_Employee WHERE empID = 2
)
GROUP BY empID, name

Related

How to combine two columns from different tables that have a similar name but have different values in SQL Server

I have three tables (example) STAFF, STU, EMP.
I want to combine the column EMPID in table STAFF and table EMP into 1 column?
My previous query is like this,
SELECT *
FROM STU s
FULL OUTER JOIN STAFF st ON st.STAFFID = STUID
FULL OUTER JOIN EMP e ON s.STUID = st.EMPID
The result is like this
The expected result is just like the above screenshot, but I want to join EMPID into one column only.
UPDATE:
I tried using this query:
SELECT
stu.stuid, stu.stuname, stu.stucode,
s.staffid, s.staffname, s.staffcode,
emp.empname, emp.empcode,
COALESCE (emp.empid, staff.staffid) AS col
FROM
STU, Staff, EMP
FULL OUTER JOIN
STAFF s ON s.STAFFID = stu.STUID
FULL OUTER JOIN
EMP e ON stu.STUID = s.EMPID
but it displays an error like this
Use below query to get the desired result.
SELECT s.StuID, s.StuName, s.Stucode, st.StaffId, st.StaffName, st.Staffcode, isnull(st.EmpId, e.EmpId) EmpId, e.EmpCode, e.EmpName
FROM STU s FULL outer JOIN
STAFF st
ON st.STAFFID = STUID FULL OUTER JOIN
EMP e
ON s.STUID = st.EMPID
Note: You will get the one emp Id column as needed. If Staff emp id is not null then staff emp id will be displayed else employee emp id will be displayed

How to get the unmatched records from two tables using Joins

I have two tables one is teacher and another is Department which is mentioned below.
Teacher Table
Id Name
1 xyz
2. Gjd
3. Dftr
4 dhdk
Department Table
Id Name EMPID
1 SQL. 2
2. PHP. 4
3. JAVA. 1
4 PEARL. 5
QUESTION
i want those records of teacher which are not link with any Department.
you can use following statement using left join then filter Teacher that not matched
SELECT t.*
FROM Teacher t
left join Department d on d.EMPID = t.Id
where d.id is null
SELECT * FROM teachers WHERE
id NOT IN (SELECT DISTINCT EMPID FROM departments) ;
Hope this helps.!!
you can do it by inner query..
select * from teacher where id not in (select empid from department);

SQL Server : replace several instances of userID with username

I may be overthinking this but I have not managed to figure it out or find a solution, so I'm hoping for a pointer in the right direction. I tried using the Select ColumnA AS Column B etc but it's not doing what I want.
I have 2 tables, scenario examples below
Table 1 (Vehicle)
VehicleID (001)
VehicleMake (Ford)
VehicleModel (Falcon)
VehicleExCleanEmpID (005)
VehicleIntCleanEmpID (003)
Table 2 (Employee)
EmpID (005)
EmpName (Dave)
The scenario being that a vehicle is cleaned internally or externally by any one of a pool of employees shown by the relevant ID in the Vehicles table.
I want to show in a query VehicleID, InsideCleanName, ExternalCleanName rather than showing the employee's ID.
So end up with results similar to this
VehicleID InsideCleanName ExternalCleanName
------------------------------------------------
001 Bob Dave
002 Sue Dave
003 John Sid
Thanks for any tips and or help
THat seems like a pretty simple query with two inner joins to the Employee table - something like this:
SELECT
v.VehicleId,
InsideCleanName = e1.EmpName,
ExternalCleanName = e2.EmpName
FROM
dbo.Vehicle v
INNER JOIN
dbo.Employee e1 ON v.VehicleIntCleanEmpId = e1.EmpID
INNER JOIN
dbo.Employee e2 ON v.VehicleExCleanEmpId = e2.EmpID
Joining to the Employee e1 table is giving you the employee who was responsible for the inside cleaning, while joining a second time, to Employee e2 gives you the one responsible for the external cleaning.
Join the two table with EmpId and select the columns you want similar to the code below:
select column1, column2 from table1 inner join table2 on table1.EmpId = table2.EmpId

Limit the data set of a single table within a multi-table sql select statement

I'm working in an Oracle environment.
In a 1:M table relationship I want to write a query that will bring me each row from the "1" table and only 1 matching row from the "many" table.
To give a made up example... ( * = Primary Key/Foreign Key )
EMPLOYEE
*emp_id
name
department
PHONE_NUMBER
*emp_id
num
There are many phone numbers for one employee.
Let's say I wanted to return all employees and only one of their phone numbers. (Please forgive the far-fetched example. I'm trying to simulate a workplace scenario)
I tried to run:
SELECT emp.*, phone.num
FROM EMPLOYEE emp
JOIN PHONE_NUMBER phone
ON emp.emp_id = phone.emp_id
WHERE phone.ROWNUM <= 1;
It turns out (and it makes sense to me now) that ROWNUM only exists within the context of the results returned from the entire query. There is not a "ROWNUM" for each table's data set.
I also tried:
SELECT emp.*, phone.num
FROM EMPLOYEE emp
JOIN PHONE_NUMBER phone
ON emp.emp_id = phone.emp_id
WHERE phone.num = (SELECT MAX(num)
FROM PHONE_NUMBER);
That one just returned me one row total. I wanted the inner SELECT to run once for each row in EMPLOYEE.
I'm not sure how else to think about this. I basically want my result set to be the number of rows in the EMPLOYEE table and for each row the first matching row in the PHONE_NUMBER table.
Obviously there are all sorts of ways to do this with procedures and scripts and such but I feel like there is a single-query solution in there somewhere...
Any ideas?
I'd use a rank (or dense_rank or row_number depending on how you want to handle ties)
SELECT *
FROM (SELECT emp.*,
phone.num,
rank() over (partition by emp.emp_id
order by phone.num) rnk
FROM EMPLOYEE emp
JOIN PHONE_NUMBER phone
ON emp.emp_id = phone.emp_id)
WHERE rnk = 1
will rank the rows in phone for each emp_id by num and return the top row. If there could be two rows for the same emp_id with the same num, rank would assign both a rnk of 1 so you'd get duplicate rows. You could add additional conditions to the order by to break the tie. Or you could use row_number rather than rank to arbitrarily break the tie.
All above answers will work beautifully with the scenario you described.
But if you have some employees which are missing in phone tables, then you need to do a left outer join like below. (I faced similar scenario where I needed isolated parents also)
EMP
---------
emp_id Name
---------
1 AA
2 BB
3 CC
PHONE
----------
emp_id no
1 7555
1 7777
2 5555
select emp.emp_id,ph.no from emp left outer join
(
select emp_id,no,
ROW_NUMBER() OVER (PARTITION BY emp_id ORDER BY emp_id) as rnum
FROM phone) ph
on emp.emp_id = ph.emp_id
where ph.rnum = 1 or ph.rnum is null
Result
EMP_ID NO
1 7555
2 5555
3 (null)
If you want only one phone number, then use row_number():
SELECT e.*, p.num
FROM EMPLOYEE emp JOIN
(SELECT p.*,
ROW_NUMBER() OVER (PARTITION BY emp_id ORDER BY emp_id) as seqnum
FROM PHONE_NUMBER p
) p
ON e.emp_id = p.emp_id and seqnum = 1;
Alternatively, you can use aggregation, to get the minimum or maximum value.
This is my solution. Simple but maybe wont scale well for lot of columns.
Sql Fiddle Demo
select e.emp_id, e.name, e.dep, min(p.phone_num)
from
EMPLOYEE e inner join
PHONE_NUMBER p on e.emp_id = p.emp_id
group by e.emp_id, e.name, e.dep
order by e.emp_id;
And this fix the query you try
Sql Fiddle 2
SELECT emp.*, phone.num
FROM EMPLOYEE emp
JOIN PHONE_NUMBER phone
ON emp.emp_id = phone.emp_id
WHERE phone.num = (SELECT MAX(num)
FROM PHONE_NUMBER p
WHERE p.emp_id = emp.emp_id );

New Sql query solution

person_id | manager_id | name |
| | |
-------------------------------
I have to display name of every person with manager name.
Yes its complete table. Thats all I have.
This one should give you all employees that have a manager, with employee_name and manager_name. Replace your_table by your table name.
If you want to get all persons, also that without manager, replace the JOIN by a LEFT JOIN. This would return NULL as manager_name for all persons without manager_id.
SELECT t1.name employee_name, t2.name manager_name
FROM [your_table] t1
JOIN [your_table] t2 ON ( t1.manager_id = t2.person_id )
Which SQL dialect? Here's some TSQL, but I'm vague to the actual question ("every person with manager name"); if you mean "given a manager name, list the people (reports)", then:
SELECT peon.[person_id], peon.[name]
FROM [thetable] mgr
INNER JOIN [thetable] peon
ON peon.manager_id = mgr.[person_id]
WHERE mgr.[name] = #name
ORDER BY peon.[name]
If you mean "list the people, along with their manager's name", then:
SELECT peon.[person_id], peon.[name], mgr.[name] AS [manager]
FROM [thetable] peon
LEFT OUTER JOIN [thetable] mgr
ON mgr.[person_id] = peon.manager_id
ORDER BY peon.[name]
SELECT person.name, manager.name
FROM table person, table manager
WHERE person.manager_id = manager.person_id