I have two tables, which I need to match on
"Fullname"
against
"FirstName" & "LastName"
and extract the userID from the "FirstName"/"LastName" table.
If there's a match retrieve the UserID if not Just Null
Example:
Table1 (With fullname)
|Sam Smith|
Must match with
Table2 (with first and last name)
| Sam | Smith |
And I would like to take into account if a person has three names.
(Fullname)
|Sam Samual Smith|
vs. (First & Last Name)
|Sam Samual | Smith |
Any help needed, not sure how to go around it,
As Lasse V. Karlsen suggested,
SELECT *
FROM [MainTable] M
INNER JOIN [SubTable] S
ON M.Fullname=S.Firstname + ' ' + S.Lastname; -- check if fullname is a of combination
-- firstname and lastname from other table
Replace the table names with your table names and put the fields you want in the select query as selecting all the fields could compromise the perfomance.
Try like this,
SELECT *
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.FullName = T2.FirstName + ' ' + T2.LastName
Related
I've got a join table that has 'account_id' and 'group id' in it, both represented by a GUID. I'm trying to merge the columns so we get a single 'account_id' with all of it's 'group_id's merged to a single Colum/row, but display the actual name of the account and group.
Tables
Account
account_id Name
1 Henry
2 Smith
Group
Group_id Group_nameName
3 User
4 Admin
Account_Group_Join_Table
account_id group_id
1 3
1 4
2 3
Desired Result:
Name Groups
Henry Dev,User
Smith User, Admin
Code so far to return 'account_id' with 'group_id' grouped to single row/column
select account_id,
stuff((SELECT distinct ', ' + group_id
FROM account_group_join t2
where t2.account_id = t1.account_id
FOR XML PATH('')),1,1,'') [Groups]
from account_group_join t1
group by account_id
You just need to join to your group table in the subquery so you can get the name rather than the ID. You also may as well just select from Account in the outer query and avoid an additional join to account to get the name:
SELECT a.account_id,
a.Name,
STUFF((SELECT DISTINCT ', ' + g.group_nameName
FROM account_group_join AS ag
INNER JOIN [Group] AS g
ON g.group_id = ag.group_id
WHERE ag.account_id = a.account_id
FOR XML PATH('')),1,1,'') AS [Groups]
from Account AS a;
n.b. I've changed your aliases from t1 and t2 to something that kind of represents the table I am aliasing, you'll find this much easier especially when working with larger queries. More reading here: Bad Habits to Kick : Using table aliases like (a, b, c) or (t1, t2, t3)
when I use concat in select formula I will get concat of other column too.
Example:
SELECT
firstname,
surname,
concat(firstname,' ',surname) AS fullname
FROM
employee
Source data:
| firstname | surname |
| John | Kenedy |
Output data:
| firstname | surname | fullname |
| Kenedy John | Kenedy | Kenedy Kenedy John |
Am I using concat wrog way?
Hello you have a bad syntax this must be work
SELECT CONCAT(firstname, ' ', surname) as fullname FROM employee;
Result:
+-----------------+
| fullname |
+-----------------+
| John Kenedy |
| Abraham Lincoln |
+-----------------+
You can get more info here
better still. don't use concat function. Use the operator || instead. If you use concat(), and you need to concatenate a bunch of things, it gets very ugly very quickly nesting all the concats within each other.
which do you prefer?
select concat('I ', concat('think ', concat('data ', concat('is ', 'fun '))))
-or-
select 'I ' || 'think ' || 'data ' || 'is ' || 'fun '
Your source data firstname column is not the same as your output data firstname column. If you were to run your concat function on the source data as you've presented it, then I believe you would get the results you expect.
Edit 1: Removing duplicate words from a record with SQL
Use a SPLIT_TO_TABLE table function to split each part of the concatenation to an individual row
Use QUALIFY clause to filter out duplicate words for each flattened record
Grouping by the firstname and surname, use a LISTAGG function to concatenate together each unique word using an ORDER BY clause to preserve the order of the words
CREATE OR REPLACE TEMPORARY TABLE TMP_EMPLOYEE
AS
SELECT $1 AS FIRSTNAME
,$2 AS SURNAME
FROM VALUES
('John','Kenedy')
,('Kenedy John','Kenedy')
;
WITH A AS (
SELECT E.FIRSTNAME
,E.SURNAME
,STT.SEQ
,STT.INDEX
,STT.VALUE
FROM TMP_EMPLOYEE E
,LATERAL SPLIT_TO_TABLE(FIRSTNAME || ' ' || SURNAME,' ') STT
QUALIFY ROW_NUMBER() OVER(PARTITION BY STT.SEQ,STT.VALUE ORDER BY STT.INDEX) = 1
)
SELECT A.FIRSTNAME
,A.SURNAME
,LISTAGG(A.VALUE,' ') WITHIN GROUP(ORDER BY A.INDEX) AS FULLNAME
FROM A
GROUP BY A.FIRSTNAME,A.SURNAME
;
Notes
This does not compare any two or more records to each other to find duplicates
I have a problem with an extraction query.
I want to extract all records that begin with exactly one name.
The problem:
Not always the end of the name is this extension;
When they are present, they have no fixed length.
Example:
TabNames
id | Name
1 | Mike
2 | Mike Nell-1
3 | Mike-2
4 | Robert-1
5 | Mike Rio-NN
6 | Mike-Orio-2
.....
Name searched for: 'Mike'
Desired outcome:
Mike, Mike-2
If interested, I use SQL Server.
How can I do?
You can do this with FOR XML. You will have update the Table Names, Columns Names and Where Statement in both select statements. This is a variation of this Concatenation Script.
SELECT DISTINCT
SUBSTRING(
(
SELECT ', '+ T1.Name AS [text()]
FROM dbo.TabNames T1
WHERE T1.Name LIKE 'Mike%'
ORDER BY T1.Name
FOR XML PATH ('')
), 3, 8000) AS Names
FROM
dbo.TabNames T2
WHERE
T2.Name LIKE 'Mike%'
How can I join two tables, where one of the tables has multiple comma separated values in one column that reference an id in another column?
1st table
Name | Course Id
====================
Zishan | 1,2,3
Ellen | 2,3,4
2nd table
course id | course name
=======================
1 | java
2 | C++
3 | oracle
4 | dot net
Maybe this uglyness, I have not checked results:
select names.name, courses.course_name
from names inner join courses
on ',' + names.course_ids + ',' like '%,' + cast(courses.course_id as nvarchar(20)) + ',%'
First of all your Database structure is not normalized and should have been. Since it is already set up this way , here's how to solve the issue.
You'll need a function to split your string first:
CREATE FUNCTION SPLIT_STRING(str VARCHAR(255), delim VARCHAR(12), pos INT) RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(str, delim, pos),
LENGTH(SUBSTRING_INDEX(str, delim, pos-1)) + 1), delim, '');
Then you'll need to create a view in order to make up for your structure:
CREATE VIEW database.viewname AS
SELECT SPLIT_STRING(CourseID, ',', n) as firstField,
SPLIT_STRING(CourseID, ',', n) as secondField,
SPLIT_STRING(CourseID, ',',n) as thirdField
FROM 1stTable;
Where n is the nth item in your list.
Now that you have a view which generates your separated fields, you can make a normal join on your view, just use your view like you would use a table.
SELECT *
FROM yourView
JOIN table1.field ON table2.field
However since I don't think you'll always have 3 values in your second field from your first table you'll need to tweak it a little more.
Inspiration of my answer from:
SQL query to split column data into rows
and
Equivalent of explode() to work with strings in MySQL
SELECT f.name,s.course_name FROM table1 AS f
INNER JOIN table2 as s ON f.course_id IN (s.course_id)
Use the Below Query For Solution
Select * from table_2 t2 INNER JOIN table_1 t1 on t1.Course Id = t2.course id
Is it possible to do bulk replace without while loop or what is the best way
Table-1
+-------+--------+
| name | value |
+-------+--------+
| #1# | one |
| #2# | two |
| #3# | three |
+-------+--------+
Table-2 (updated: there is more than one different tokens in table2)
+-----------------------+
| col1 |
+-----------------------+
| string #1# string #2# |
| string #2# string #1# |
| string #3# string #2# |
+-----------------------+
I like to replace all token from Table-2 with Table-1's value column respectively.
Expected Result
+-------------------------+
| col1 |
+-------------------------+
| string one string two |
| string two string one |
| string three string two |
+-------------------------+
Current solution with While loop
declare #table1 table(name nvarchar(50),value nvarchar(50))
insert into #table1 values('#1#','one'),('#2#','two'),('#1#','three')
declare #table2 table(col1 nvarchar(50))
insert into #table2 values('string #1# string #2#'),('string #2# string #1#'),('string #3# string #2#')
WHILE EXISTS (SELECT 1 FROM #table2 t2 INNER JOIN #table1 t1 ON CHARINDEX(t1.name,[col1])>0)
BEGIN
UPDATE #table2
SET col1=REPLACE(col1,name,value)
FROM #table1
WHERE CHARINDEX(name,[col1])>0
END
select * from #table2
Thanks
I suppose you use Sql Server (you've tagged with tsql):
I've run this query on Sql fiddle with 2012 version, but on my PC I've tried with 2008r2 version.
You can procede in this way:
UPDATE table2
SET col1 = REPLACE(col1,
(SELECT name FROM table1 WHERE col1 LIKE '%' + table1.NAME + '%'),
(SELECT value FROM table1 WHERE col1 LIKE '%' + table1.NAME + '%'))
Sql Fiddle
If you want show only the value without UPDATE you can proceed in this way:
SELECT REPLACE(T2.col1, T1.name, T1.value)
FROM table1 T1
JOIN table2 T2
ON T2.col LIKE '%' T1.name + '%'
EDIT
After editing of question / comment my answer is not complete because on the same row can exist more one token. I'm thinking... :)
I thought: :D
IMHO: You must create a loop on your table because the presence of several tokens don't resolve with a single UPDATE statement with subquery, because as you written, the subquery return more than one value.
In Sql Server the REPLACE function change only token, so if you want change in one step two token you must nest your REPLACE function, but we have a number undefined of token in a row so we can't prevent to apply the exact number of REPLACE. An help you can have using a cursor and a dynamic SQL query build on runtime, so you can do a single UPDATE per row. If you want a guide line to use CURSOR and DYNAMIC SQL, please write me. Good night ;)
You can do bulk replacement with this simple piece of code:
update #table2
set col1= left(a.col1,6)+' ' + b.value from #table2 a
join #table1 b on b.name=substring(a.col1,8,3)
select * from #table2
Basically, it updates the column with a new field value.