SQL UPDATE part of a string with value from other table - sql

I need to replace part of a string with a value from another database table. Actually I need to replace the userids with emails.
DB1.TABLE1
ID|EMAIL
1 |johndoe; janedoe;
2 |otherguy; johndoe;
DB2.TABLE2
ID|USERID |EMAIL
1 |johndoe |johndoe#test.com
2 |janedoe |janedoe#test.com
3 |otherguy|otherguy#test.com
my query
UPDATE
TABLE1
set
EMAIL = TABLE2.EMAIL
from
DB2.TABLE2
where
TABLE1.EMAIL = TABLE2.USERID
How can I specify the "part of the string" thing ?

There are a number of comments about changing your schema...which would be the best way forward.
It looks like what you are storing in table1.email is actually a list of UserId from table2. So you'll need to break out these ids in order to join to the tables together.
If you absolutely must follow this path, then there are existing Q+As on the site that will help you:
(I've taken a leap of faith that you are using SQL server ... but if you search I'm sure you can find similar answers for other RDBMSs)
Turning a Comma Separated string into individual rows
and
Multiple rows to one comma separated value

I guess you need the following
UPDATE TABLE1
SET EMAIL = (
SELECT TABLE2.EMAIL
FROM TABLE2
WHERE TABLE1.EMAIL LIKE TABLE2.USERID + '%');
demo

Related

How to make a new column in SELECT clause and fill it with a string/list dynamically with concat of all condition statements satisfied?

So there are two tables in a database. I have to find out whichever rows have discrepancy based on certain conditions (in couple of cases that's just equality checking between fields). I report ID of those rows.
The problem is to also include the reasons in another column as to why that ID is reported. Because an id can be fail multiple conditions (like mismatch on two fields), I just wanted to include all of those reasons in another column.
Basic idea is to append all the mismatches in another column.
I've looked at several SO questions but they don't exactly my use case. So now I'm thinking it's not possible with SQL.
I searched Google for "enter dynamic column values based on conditions sql", and hit : SQL Conditional column data return in a select statement : This adds a static column
I also learned it's possible to add another column in SELECT with dynamic content like this:
SELECT id, CASE
WHEN columnname "DEF" then "I" ELSE "YOU" newColumnName
FROM tableName
But I have not been able to find dynamic column value assignment and update SQL. That's the problem.
Expected results:
I just want to be able to concat all the cases "strings" which a record is applicable for.
Do this with the two tables.
So because I have two tables to work with I have to put these conditions in the WHERE sub-clause, and not in the SELECT one.
So, if for ID = 345, column "FOO_MAN" does not match between two tables, and column "BAR_TOO" also does not match between two tables, then?
Then I want my select clause to capture information like this:
ID | REASON
345 | FOO_MAN BAR_TWO
It's probably easier to build this type of query dynamically (e.g. using a stored procedure) based on the conditions you want to test, but here is a small example which shows how it can be done:
SELECT t1.id,
CONCAT_WS(' ',
CASE WHEN t1.foo != t2.foo THEN 'foo' END,
CASE WHEN t1.bar != t2.bar THEN 'bar' END
) AS reason
FROM t1
JOIN t2 ON t2.id = t1.id
WHERE t1.foo != t2.foo OR t1.bar != t2.bar
Output (for my demo on dbfiddle)
id reason
2 foo
4 bar
5 foo bar

SQL DISTINCT value within a field

I know how to select distinct rows, but I can't find how to extract distinct 'words/string/data' from a field to update another column.
For example, if I have data in a table like so..
Table 1
ID TEXTDATA
123 ROCK DANCE ROCK INDIE ROCK POP DISCO EURO POP
456 POP DANCE DISCO POP
I want to UPDATE another field in another table with 'distinct' data from within the TEXTDATA fields, so it would look like this
Table 2
ID NEWTEXTDATA
123 ROCK DANCE INDIE POP DISCO EURO
456 POP DANCE DISCO
I worked out how to Update one table with data from another...
UPDATE table2 JOIN table1 ON table2.ID = table1.ID SET table2.NEWTEXTDATA = table1.TEXTDATA;
But I want it to be of distinct values within the TEXTDATA records. Hope that makes some sort of sense. Is that possible to do within an update query?
Many thanks in advance
For Sql Server 2008:
You can do this by using the xml query with distinct values. The below code will give you the distinct records from given row.
cast(cast('<d>'+replace(TEXTDATA, ' ','</d><d>')+'</d>' as xml).query('distinct-values(/d)') as varchar(max))
So with the help of above function your final query will be something like below.
UPDATE
table2
SET
NEWTEXTDATA = cast(cast('<d>'+replace(TEXTDATA, ' ','</d><d>')+'</d>' as xml).query('distinct-values(/d)') as varchar(max))
FROM
table2 t2
JOIN
table1 t1
ON
t2.ID = t1.ID;
Here is the working SQLFiddle for same.
For MySql: There is no way in MySql to achieve this.
Normalize your database.
get values from table and use php explode() , and use array_unique to remove duplicate values.

Uniqe Replace Query

I have table1 that has full lastname and full firstname.
I have table2 that has full lastname and just the first letter of the first name in the firstname field.
I want to replace table2 firstname with the fristname in table1. The problem is that in both tables there are several people with the same last name.
The id in both tables are different and won't match.
Any way to relate table1 firstname with table2 firstname with a replace query?
Exactly how to do it depends on the DBMS you are using, but I think something like this should do the trick. Inspired by answers to this question.
UPDATE table2
SET table2.firstname = table1.firstname
FROM table1, table2
WHERE
table1.lastname = table2.lastname AND
table1.firstname LIKE CONCAT(table2.firstname, '%')
The WHERE conditions finds a match in table1 that has the same lastname as in table2, and whos firstname begins with the same string. CONCAT is string concatenation, so you would get something looking like 'Bobby' LIKE 'Bob%'.
Please note, that if there are several matches for one row in table2 (for instance, both Anna Smith and Anastasia Smith matching An... Smith), that row will be updated with both. The last one will be the one who sticks, but which one who happend to be last is pretty much random. To check if you have any cases like that, I think you could run this query:
SELECT table2.firstname, table2.lastname
FROM table1, table2
WHERE
table1.lastname = table2.lastname AND
table1.firstname LIKE CONCAT(table2.firstname, '%')
GROUP BY table2.firstname, table2.lastname
HAVING COUNT(*) > 1
Disclaimar: I have not tested any of this.
First check whether you have duplicate combinations in table2:
SELECT lastname, name, count(*)
FROM table2
GROUP BY lastname, name
HAVING count(*) > 1
If you don't have duplicates in table2 solution is easy, you can join tables like this:
... t1.lastname = t2.lastname
AND SUBSTRING(t1.name, 1, 1,) = t2.name
As exact db is not specified in the question, I am skipping the complete UPDATE query here.
If first query returns duplicates, you will need to deal with those. If you update those records first with appropriate names, you will be able to run the update query, as it will only affect records where name is single char in table2.

Compare comma separated list with individual row in table

I have to compare comma separated values with a column in the table and find out which values are not in database. [kind of master data validation]. Please have a look at the sample data below:
table data in database:
id name
1 abc
2 def
3 ghi
SQL part :
Here i am getting comma separated list like ('abc','def','ghi','xyz').
now xyz is invalid value, so i want to take that value and return it as output saying "invalid value".
It is possible if i split those value, take it in temp table, loop through each value and compare one by one.
but is there any other optimal way to do this ??
I'm sure if I got the question right, however, I would personally be trying to get to something like this:
SELECT
D.id,
CASE
WHEN B.Name IS NULL THEN D.name
ELSE "invalid value"
END
FROM
data AS D
INNER JOIN badNames B ON b.Name = d.Name
--as SQL is case insensitive, equal sign should work
There is one table with bad names or invalid values if You prefer. This can a temporary table as well - depending on usage (a black-listed words should be a table, ad hoc invalid values provided by a service should be temp table, etc.).
NOTE: The select above can be nested in a view, so the data remain as they were, yet you gain the correctness information. Otherwise I would create a cursor inside a function that would go through the select like the one above and alter the original data, if that is the goal...
It sounds like you just need a NOT EXISTS / LEFT JOIN, as in:
SELECT tmp.InvalidValue
FROM dbo.HopeThisIsNotAWhileBasedSplit(#CSVlist) tmp
WHERE NOT EXISTS (
SELECT *
FROM dbo.Table tbl
WHERE tbl.Field = tmp.InvalidValue
);
Of course, depending on the size of the CSV list coming in, the number of rows in the table you are checking, and the style of splitter you are using, it might be better to dump the CSV to a temp table first (as you mentioned doing in the question).
Try following query:
SELECT SplitedValues.name,
CASE WHEN YourTable.Id IS NULL THEN 'invalid value' ELSE NULL END AS Result
FROM SplitedValues
LEFT JOIN yourTable ON SplitedValues.name = YourTable.name

select query to perform data existance in other table where data need to split and each part need to check

I dont want to use any function or any procedure.
I want simple select query to check the existance of the each part of string.
like i have one table dummy which have name column
Id name
1 as;as;as
2 asd;rt
and child table
child_id name
23 as
24 asd
25 rt
so any i can do that
i have tried like
select substr(first_name,1,instr(first_name,';')-1) from dummy;
select substr(first_name,instr(first_name,';')+1,instr(first_name,';')-1)
from dummy;
Which is giving only first/second part but other part
how to get other part
If I've got it right - You need to join these tables if child's NAME is included in a DUMMY.Name
SQLFiddle example
select t1.*,
t2.child_id,
t2.name as t2name
from t1
left join t2 on (';'||t1.name||';' like '%;'||t2.name||';%')
I would need more information on this question. We do not know if you have to detect more than one of the possible strings on just one field.
You could use three like clauses for the three possible scenarios
LIKE column_name ||'%;'
LIKE '%;'|| column_name
LIKE ';%'|| column_name ||'%;'
But it would probably work better for the future learning about building regular expressions. Here is a webpage that helped me a lot: txt2re.com