SQL Join on Like Operator - sql

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

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 do I write a program that duplicates a row when multiple values in one column are assigned to a single value in another?

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
);

Aggregate operation oracle

I have two tables and I need to find the person with the highest value.
TABLE1
NAME ID
--------------- ---------------
MIKE 101
MIKE 102
BETTY 103
BETTY 104
BETTY 105
TIM 106
TABLE2
ID VALUE
-------- --------------
101 12
102 10
103 20
104 20
105 10
106 5
I can write a select statement that will give a result of name and values:
SELECT name, value
FROM table1, table2
WHERE table1.id = table.id;
NAME VALUE
----- ----------
MIKE 12
MIKE 10
BETTY 20
BETTY 20
BETTY 10
TIM 5
Now I need to aggregate the values of the rows with equal names and I can not figure it out. Am I going about it the correct way?
Please try this :
select a.name,max(b.value) as value
from table1 a
inner join table2 b on a.id = b.id
group by a.name
Anyway, you tagged mysql and oracle in the question. Luckily, this sql works in both. But you have to remove one of these two tags, to make sure which dbms are you use.
Use this.. and since your column names are unique, you don't need any alias.
select name, max(value) as MaxValue
from table1
inner join table2 on table1.id = table2.id
group by name

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)))

Select query which returns exect no of rows as compare in values of sub query

I have got a table named student. I have written this query:
select * From student where sname in ('rajesh','rohit','rajesh')
In the above query it's returning me two records; one matching 'rajesh' and another matching: 'rohit'.
But i want there to be 3 records: 2 for 'rajesh' and 1 for 'rohit'.
Please provide me some solution or tell me where i am missing.
NOTE: the count of result of sub query is not fix there can be many words there some distinct and some multiple occurrence .
Thanks
Your requirements are not clear, and I'll try to explain why.
Let's define table students
ID FirstName LastName
1 John Smith
2 Mike Smith
3 Ben Bray
4 John Bray
5 John Smith
6 Bill Lynch
7 Bill Smith
Query with WHERE clause:
FirstName in ('Mike', 'Ben', 'Mike')
will return 2 rows only, because it could be rewritten as:
FirstName='Mike' or FirstName='Ben' or FirstName='Mike'
WHERE is filtering clause that just says if existing row satisfy given conditions or not (for each of rows created by FROM clause.
Let's say we have subquery that returns any number of non distinct FirstNames
In case if SQ contains 'Mike', 'Ben', 'Mike' using inner join you can get those 3 rows without problem
Select ST.* from Students ST
Inner Join (Select name from …. <your subquery>) SQ
On ST.FirstName=SQ.name
Result will be:
ID FirstName LastName
2 Mike Smith
2 Mike Smith
3 Ben Bray
Note data are not ordered by order of names returning by SQ. If you want that, SQ should return some ordering number, eg.:
Ord Name
1. Mike
2. Ben
3. Mike
In that case query should be:
Select ST.* from Students ST
Inner Join (Select ord, name from …. <your subquery>) SQ
On ST.FirstName=SQ.name
Order By SQ.ord
And result:
ID FirstName LastName
2 Mike Smith (1)
3 Ben Bray (2)
2 Mike Smith (3)
Now, let's se what will happen if subquery returns
Ord Name
1. Mike
2. Bill
3. Mike
You will end up with
ID FirstName LastName
2 Mike Smith (1)
6 Bill Lynch (2)
7 Bill Smith (2)
2 Mike Smith (3)
Even worse, if you have something like:
Ord Name
1. John
2. Bill
3. John
Result is:
ID FirstName LastName
1 John Smith (1)
4 John Bray (1)
5 John Smith (1)
6 Bill Lynch (2)
7 Bill Smith (2)
1 John Smith (3)
4 John Bray (3)
5 John Smith (3)
This is an complex situation, and you have to clarify precisely what requirement is.
If you need only one student with the same name, for each of rows in SQ, you can use something like SQL 2005+):
;With st1 as
(
Select Row_Number() over (Partition by SQ.ord Order By ID) as rowNum,
ST.ID,
ST.FirstName,
ST.LastName,
SQ.ord
from Students ST
Inner Join (Select ord, name from …. <your subquery>) SQ
On ST.FirstName=SQ.name
)
Select ID, FirstName, LastName
From st1
Where rowNum=1 -- that was missing row, added later
Order By ord
It will return (for SQ values John, Bill, John)
ID FirstName LastName
1 John Smith (1)
6 Bill Lynch (2)
1 John Smith (3)
Note, numbers (1),(2),(3) are shown to display value of ord although they are not returned by query.
If you can split the where clause in your calling code, you could perform a UNION ALL on each clause.
SELECT * FROM Student WHERE sname = 'rajesh'
UNION ALL SELECT * FROM Student WHERE sname = 'rohit'
UNION ALL SELECT * FROM Student WHERE sname = 'rajesh'
Try using a JOIN:
SELECT ...
FROM Student s
INNER JOIN (
SELECT 'rajesh' AS sname
UNION ALL
SELECT 'rohit'
UNION ALL
SELECT 'rajesh') t ON s.sname = t.sname
just because you've got a criteria in there two times doesn't mean that it will return 1 result per criteria. SQL engines usually just use the unique criteria - thus, from your example, there will be 2 criteria in IN clause: 'rajesh','rohit'
WHY do you need to return 2 results? are there two rajesh in your table? they should BOTH return then. You don't need to ask for rajesh twice for that to happen. What does your data look like? What do you want to see returned?
Hi i am query just as you give above and it give me all data that matches in the condition of in clause. just like your post
select * from person
where personid in (
'Carson','Kim','Carson'
)
order by FirstName
and its give me all records which fulfill this Criteria