How do I write a program that duplicates a row when multiple values in one column are assigned to a single value in another? - sql

I have three tables:
table1:
MODULE
EMPLOYEE
A
Billy Bob
A
Billy Joe
B
John Doe
B
Jane Doe
C
Catey Rice
table2: Primary_Key = (MATERIAL_ID, MATERIAL_NUM)
MATERIAL_ID
MATERIAL_NUM
MODULE
11111111111
222222222222
A
11111111112
222222222223
B
11111111113
222222222224
C
and I need a query that will fill in my third table so that it looks like this:
table3: Foreign_Key = (MATERIAL_ID, MATERIAL_NUM)
MATERIAL_ID
MATERIAL_NUM
EMPLOYEE
11111111111
222222222222
Billy Bob
11111111111
222222222222
Billy Joe
11111111112
222222222223
John Doe
11111111112
222222222223
Jane Doe
11111111113
222222222224
Catey Rice
I tried this query:
INSERT INTO table3(EMPLOYEE)
SELECT t1.EMPLOYEE
FROM table1 t1
FULL OUTER JOIN table2 t2
ON t1.MODULE = t2.MODULE;
I already have MATERIAL_ID and MATERIAL_NUM filled in on table3 by inserting the data from table2. If I need to do it over with EMPLOYEE in the query I'll just empty the table and rewrite it.
The issue I am running into is this error: ORA-01400: cannot insert NULL into ("MATERIAL_ID"),
which I figure is happening because I don't have a method that duplicates the rows as multiple
names fill out the same MATERIAL_ID and MATERIAL_NUM. So I need help to create the method to
do that.

I think you want to UPDATE the employee column, not INSERT new rows:
update table3 t3
set employee = (select t1.employee
from table1 t1 join
table2 t2
on t2.module = t1.module
where t3.materialid = t2.materialid
);

Related

Getting records from 2 tables with common an uncommon columns

Below is similar example of the issue I have:
if I have this table 1:
Patient ID
Name
Check in Date
order name
preformed by
1
Jack
12/sep/2002
xray
Dr.Amal
2
Nora
15/oct/2002
ultrasound
Dr.Goerge
1
Jack
13/nov/2003
Medicine
Dr.Fred
table 2:
Patient ID
Name
Check in Date
order name
1
Jack
14/Jun/2002
xray 2
2
Nora
15/oct/2002
ultrasound
1
Jack
13/nov/2003
Medicine
3
Rafael
13/nov/2003
Vaccine
The result I need is as the following:
Name
Check in Date
order name
preformed by
Jack
12/sep/2002
xray
Dr.Amal
Nora
15/oct/2002
ultrasound
Dr.Goerge
Jack
13/nov/2003
Medicine
Dr.Fred
Jack
14/Jun/2002
xray 2
Null
Rafael
13/nov/2003
Vaccine
Null
If you noticed the result I need is all records of table 1 and all records of table 2 with no duplication and joining the same common fields and adding 'Preformed by' column from Table 1. I tried using 'UNION' as the following:
SELECT Name, Check_in_Date, order_name,preformed_by
FROM table1
UNION
SELECT Name, Check_in_Date, order_name,''
FROM table2
the result I get is 2 records for each patient with the same date one with preformed by one with null as the following:
Name
Check in Date
order name
preformed by
Jack
12/sep/2002
xray
Dr.Amal
Nora
15/oct/2002
ultrasound
Dr.Goerge
Nora
15/oct/2002
ultrasound
Null
Jack
13/nov/2003
Medicine
Dr.Fred
Jack
13/nov/2003
Medicine
null
Jack
14/Jun/2002
xray 2
Null
Rafael
13/nov/2003
Vaccine
Null
If the same ID has same check in date in both table it must return the preformed by of table 1 not null How can I do this?
Thank you.
What you need is a FULL JOIN matching by those three columns along with NVL() function in order to bring the values
from table2 which return null from table1 such as
SELECT NVL(t1.name,t2.name) AS name,
NVL(t1.check_in_date,t2.check_in_date) AS check_in_date,
NVL(t1.order_name,t2.order_name) AS order_name,
t1.preformed_by
FROM table1 t1
FULL JOIN table2 t2
ON t1.name = t2.name
AND t1.check_in_date = t2.check_in_date
AND t1.order_name = t2.order_name
or another method uses UNION to filter out duplicates and then applies an OUTER JOIN such as
SELECT tt.name, tt.check_in_date, tt.order_name, t1.preformed_by
FROM (
SELECT name, check_in_date, order_name FROM table1 UNION
SELECT name, check_in_date, order_name FROM table2
) tt
LEFT JOIN table1 t1
ON t1.name = tt.name
AND t1.check_in_date = tt.check_in_date
AND t1.order_name = tt.order_name
Demo

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

Creating one new column out of two existing columns

I have this table t1 with c1:old_email and c2:new_email
The goal: I want to create a new column/or query this table in a way so that I can use fields from c1 and c2 (basically merge the results from c1 and c2 into one column c3) and use it for a subquery in a where statement:
Select * from t2 where t2.email=(select c3 from t1)
name |old_email |new_email
:Johnny Go: JG#yahoo.com:
:Bertie Post: Bertie#hotmail.com: Bertie#gmail.com:
can't you join using both conditions?
select t2.* from
t2 join t1 on t2.email in (t1.old_email, t1.new_email)
or
select t2.*
from t1, t2
where t2.email = t1.old_email
or t2.email = t1.new_email
The question is a little ambiguous. I am going to infer you have a table like the one below, and you want to match either email address by joining a separate table of email addresses you have to identify matches.
ID
NAME
OLD_EMAIL
NEW_EMAIL
1
David Lin
david.lin#example.com
david#fakegoofmail.com
2
Christy Thomas
christy.thomas#example.com
christy#fakegoofmail.com
3
Erin Hill
erin.hill#example.com
erin#fakegoofmail.com
4
Noah Collins
noah.collins#example.com
noah#fakegoofmail.com
5
Andrew Salazar
andrew.salazar#example.com
andrew#fakegoofmail.com
You are going to want to put both old_email and new_email in one column. We can do this with unpivot.
select
p.*
from t1
unpivot(email for email_field in (old_email, new_email)) p;
The result would look like so.
ID
NAME
EMAIL_FIELD
EMAIL
1
David Lin
OLD_EMAIL
david.lin#example.com
1
David Lin
NEW_EMAIL
david#fakegoofmail.com
2
Christy Thomas
OLD_EMAIL
christy.thomas#example.com
2
Christy Thomas
NEW_EMAIL
christy#fakegoofmail.com
3
Erin Hill
OLD_EMAIL
erin.hill#example.com
3
Erin Hill
NEW_EMAIL
erin#fakegoofmail.com
4
Noah Collins
OLD_EMAIL
noah.collins#example.com
4
Noah Collins
NEW_EMAIL
noah#fakegoofmail.com
5
Andrew Salazar
OLD_EMAIL
andrew.salazar#example.com
5
Andrew Salazar
NEW_EMAIL
andrew#fakegoofmail.com
Now you can join your secondary table of emails to perform email matching with a query like something below.
with t1_cte as (
select
p.*
from t1
unpivot(email for email_field in (old_email, new_email)) p order by 1
)
select t1.* from t1_cte t1
inner join seperate_table_of_emails t2 -- << your secondary table
on t1.email = t2.email;

SQL Join on Like Operator

I know this question has been asked a couple of times and i've tried to use the solution for my problem. Unfortunately it did not get me the output i wanted. I need to update ID column in one table by joining it to another table where the joining column does not have exact value.
TableA TableB
EmpNo EmpName ID EmpNo EmpName ID TermDate
101 John Doe Null 250termed_101 John Doe 250 11-15-2018
102 Jane Doe Null 251termed_102 Jane Doe 251 02-25-2019
101 Bryan Adams Null 252termed_101 Bryan Adams 252 03-12-2020
Here's what i tried but was unable to get the required output because the below query is giving me duplicates:
select *
from TableA as A left join
TableB as B
on B.EmpNo like '%' + A.EmpNo + '%' and A.EmpNo is not null
Output Required:
EmpNo EmpName ID
101 John Doe 250
102 Jane Doe 251
101 Bryan Adams 252
I need to populate ID column from TableB into TableA by joining these 2 tables on EmpNo. For the first record, John Doe is terminated on 11-15-2018 and his employee number is assigned to Bryan Adams with unique ID. I need to populate the ID column from TableB into Table A for the corresponding employee who had that number at the time.
Thanks in advance
If your problem is truly that you're getting duplicates that you don't want, you can throw a DISTINCT in. But your problem is in the data: Bryan Adams and John Doe both have employee numbers of 101, so they look duplicated when you join to TableB.
This SQL Fiddle might help you: http://sqlfiddle.com/#!18/f30476/10
You seem on the right path, the update statement should look like the following, also notice how I am making the like comparison more accurate:
update A SET
ID = B.ID
from
TableA as A
left join TableB as B on
B.EmpNo like '%_' + A.EmpNo and
A.EmpNo is not null;
that will break when you have 101 and 1101 or 2101, so it's not a good match, so let's revisit:
update A SET
ID = B.ID
from
TableA as A
inner join TableB as B on
RIGHT(B.EmpNo, len(B.EmpNo) - charindex('_', B.EmpNo)) = A.EmpNo
A.EmpNo is not null and --you don't need this,
charindex('_', B.EmpNo) > 0;--needed, otherwise you get string errors

Access 2007 SQL Merge tables without creating duplicates

I would like to add the unique values of tblA to tblB without creating duplicate values based on multiple fields. In the following example, FirstName and LastName determine a duplicate, Foo and Source are irrelevant.
tblA:
FirstName LastName Foo Source
John Doe 1 A
Jane Doe 2 A
Steve Smith 3 A
Bill Johnson 2 A
tblB:
FirstName LastName Foo Source
John Doe 1 B
Bob Smith 5 B
Steve Smith 4 B
This is the result I want:
tblA:
FirstName LastName Foo Source
John Doe 1 A
Jane Doe 2 A
Steve Smith 3 A
Bill Johnson 2 A
Bob Smith 5 B
Here's an equivalent of the code I've tried:
INSERT INTO tblA
SELECT B.*
FROM tblB AS B
LEFT JOIN tblA AS A ON A.FirstName = B.FirstName AND A.LastName = B.LastName
WHERE A.FirstName IS NULL
And this is the result I get:
tblA:
FirstName LastName Foo Source
John Doe 1 A
Jane Doe 2 A
Steve Smith 3 A
Bill Johnson 2 A
John Doe 1 B
Bob Smith 5 B
Steve Smith from tblB is ignored, which is good. John Doe from tblB is added, which is bad. I've spent way too much time on this and I've inspected the data every way I can think of to ensure John Doe in tblA and tblB are the same first and last name. Any ideas on what could be going wrong?
Update: FYI, on my real tblB, about 10,000 of 30,000 should be moved to tblA. This is actually moving over 21,000. The problem is this is one step of a common process.
When I try:
SELECT tbb.*
FROM tbb
LEFT JOIN tba
ON (tbb.FirstName = tba.FirstName)
AND (tbb.LastName = tba.LastName)
WHERE (((tba.LastName) Is Null));
The only line returned is:
Bob Smith 5 B
Is it possible that John Doe has a hidden character?
Edit : Sorry, it doesn't work on Access2007
You have many way to do that :
INSERT INTO tblA
SELECT B.* FROM tblB AS B
WHERE B.firstname, B.lastname NOT IN (select firstname, lastname from tblA)
Or
INSERT INTO tblA
SELECT * FROM tblB
MINUS
SELECT * FROM tblA
This one works in Access.
You can run it to infinity - it won't add more rows than needed:
INSERT INTO tblA
SELECT B.*
FROM tblB AS B
WHERE (((B.FirstName) Not In (select firstname from tblA))
AND ((B.LastName) Not In (select firstname from tblA)))