Extracting Number From String SQL - mysql

I have a normal SQL statement:
SELECT VALUE_ID, UF_CRM_TASK FROM b_uts_tasks_task
Now this returns a a different field everytime but they take the form of the following:
a:1:{i:0;s:7:"CO_2012";} or a:1:{i:0;s:5:"CO_12";} or a:1:{i:0;s:7:"CO_2017";}
Basically they're different everytime. What I need is to just get the number after the CO_ part. I have tried TRIM but because everything changes in the leading and trailing section I don't think this would work.
I have looked on Stack Overflow for a while and cannot find it. I know how to do it in PHP:
$data = $row['UF_CRM_TASK'];
$companyID = substr($data, strpos($data, "CO_") + 1);
$newCompanyID = preg_replace('/[^0-9.]+/', '', $companyID);
But not SQL. Thanks in advance

In MYSQL is a bit ugly:
/*SUBSTRING_INDEX BASED ON CO_ AND THE LAST " - in 2 SUBSTRINGS*/
SELECT `VALUE_ID`, SUBSTRING_INDEX(SUBSTRING_INDEX(`UF_CRM_TASK`, 'CO_', -1), '"', 1) AS `COMPANY_ID` FROM `b_uts_tasks_task`
In PHP you can just unserialize():
$data = unserialize($row['UF_CRM_TASK']);
$companyID = str_replace('CO_', '', $data[0]);
eg:
$data = unserialize('a:1:{i:0;s:5:"CO_12";}');
echo str_replace('CO_', '', $data[0]);
//==> 12

You need to use CharIndex and SubString (Microsoft SQL) or
This is the sample code I made for my Microsoft SQL server:
declare #companyIdString varchar(50) = 'a:1:{i:0;s:7:"CO_2012";}'
print 'Company ID in a string: ' + #companyIdString
print 'Find first position: ' + Cast(charindex('"CO_', #companyIdString) as varchar(2))
print 'Locate the second position (the last "): ' + Cast(charindex('"', #companyIdString, charindex('"CO_', #companyIdString)+4) as varchar(2))
print 'Extracted Company Id: ' + substring(#companyIdString,charindex('"CO_', #companyIdString)+4, charindex('"', #companyIdString, charindex('"CO_', #companyIdString)+4) - charindex('"CO_', #companyIdString) - 4)
select
#companyIdString as CompanyIdString,
substring(#companyIdString,charindex('"CO_', #companyIdString)+4, charindex('"', #companyIdString, charindex('"CO_', #companyIdString)+4) - charindex('"CO_', #companyIdString) - 4) as CompanyId
I also made the same code on a mySQL server:
set #companyIdString := 'a:1:{i:0;s:7:"CO_2012";}';
select
#companyIdString as CompanyIdString,
substring_index(substring_index(substring_index(#companyIdString, '"', 2), '"', -1), '_', -1) as CompanyId
The substring_index starts by locating the second " (string is now a:1:{i:0;s:7:"CO_2012), then it searches backward with the -1 to locate the first " (string is now CO_2012). And then it searches backward for the underscore (string is now 2012).

Related

Check for a substring in MySQL and return a value based on it

I have an SQL query that returns the following values:
BC - Worces
BC Bristol
BC Central
BC Torquay
BC-Bath
BC-Exeter
BC-Payroll
So, we have some BC with just a space, some with a dash and some with a dash with spaces on either side. When returning these values, I want to replace any of these BC variants with "Business Continuity: " followed by Bath, or Exeter etc.
Is there a way of checking what value is returned and (I'm assuming in a separate column) returning a field based on it? If every iteration was the same, I could just use Trim, but it's the variation that's throwing me out.
You could use a case on the select
CASE WHEN Left(`colname`, 5) = 'BC - ' THEN CONCAT('Business Continuity: ', SUBSTRING(`colname`, 6))
WHEN Left(colname, 3) = 'BC ' THEN CONCAT('Business Continuity: ', SUBSTRING(`colname`, 4))
WHEN Left(`colname`, 3) = 'BC-' THEN CONCAT('Business Continuity: ', SUBSTRING(`colname`, 4))
ELSE `colname`
END as `colname`
You can use REPLACE function along with CASE statement for this.
SELECT CASE
WHEN `col_name` LIKE 'BC %' THEN REPLACE(`col_name`, 'BC ', 'Business Continuity: ')
WHEN `col_name` LIKE 'BC-%' THEN REPLACE(`col_name`, 'BC-', 'Business Continuity: ')
ELSE `col_name`
END as `col_name` FROM `table_name`;
*Not tested
select 'Business Continuity:' + SUBSTRING(REPLACE(fieldname, 'BC - ', 'BC-'), 4) from table;
Replaces all instances of 'BC - ' with 'BC-'.
Substrings everything from 4 characters onwards ie 'BC-' and 'BC '

Splitting a single column (name) into two (forename, surname) in SQL

Currently I'm working on a database redesign project. A large bulk of this project is pulling data from the old database and importing it into the new one.
One of the columns in a table from the old database is called 'name'. It contains a forename and a surname all in one field (ugh). The new table has two columns; forenames and surname. I need to come up with a clean, efficient way to split this single column into two.
For now I'd like to do everything in the same table and then I can easily transfer it across.
3 columns:
Name (the forename and surname)
Forename (currently empty, first half of name should go here)
Surname (currently empty, second half of name should go here)
What I need to do: Split name in half and place into forename and surname
If anyone could shed some light on how to do this kind of thing I would really appreciate it as I haven't done anything like this in SQL before.
Database engine: MySQL
Storage engine: InnoDB
A quick solution is to use SUBSTRING_INDEX to get everything at the left of the first space, and everything past the first space:
UPDATE tablename
SET
Forename = SUBSTRING_INDEX(Name, ' ', 1),
Surname = SUBSTRING_INDEX(Name, ' ', -1)
Please see fiddle here. It is not perfect, as a name could have multiple spaces, but it can be a good query to start with and it works for most names.
Try this:
insert into new_table (forename, lastName, ...)
select
substring_index(name, ' ', 1),
substring(name from instr(name, ' ') + 1),
...
from old_table
This assumes the first word is the forename, and the rest the is lastname, which correctly handles multi-word last names like "John De Lacey"
For the people who wants to handle fullname: John -> firstname: John, lastname: null
SELECT
if( INSTR(`name`, ' ')=0,
TRIM(SUBSTRING(`name`, INSTR(`name`, ' ')+1)),
TRIM(SUBSTRING(`name`, 1, INSTR(`name`, ' ')-1)) ) first_name,
if( INSTR(`name`, ' ')=0,
null,
TRIM(SUBSTRING(`name`, INSTR(`name`, ' ')+1)) ) last_name
It works fine with John Doe. However if user just fill in John with no last name, SUBSTRING(name, INSTR(name, ' ')+1)) as lastname will return John instead of null and firstname will be null with SUBSTRING(name, 1, INSTR(name, ' ')-1).
In my case I added if condition check to correctly determine lastname and trim to prevent multiple spaces between them.
This improves upon the answer given, consider entry like this "Jack Smith Smithson", if you need just first and last name, and you want first name to be "Jack Smith" and last name "Smithson", then you need query like this:
-- MySQL
SELECT
SUBSTR(full_name, 1, length(full_name) - length(SUBSTRING_INDEX(full_name, ' ', -1)) - 1) as first_name,
SUBSTRING_INDEX(full_name, ' ', -1) as last_name
FROM yourtable
Just wanted to share my solution. It also works with middle names. The middle name will be added to the first name.
SELECT
TRIM(SUBSTRING(name,1, LENGTH(name)- LENGTH(SUBSTRING_INDEX(name, ' ', -1)))) AS firstname,
SUBSTRING_INDEX(name, ' ', -1) AS lastname
I had a similar problem but with Names containing multiple names, eg. "FirstName MiddleNames LastName" and it should be "MiddleNames" and not "MiddleName".
So I used a combo of substring() and reverse() to solve my problem:
select
SystemUser.Email,
SystemUser.Name,
Substring(SystemUser.Name, 1, instr(SystemUser.Name, ' ')) as 'First Name',
reverse(Substring(reverse(SystemUser.Name), 1, instr(reverse(SystemUser.Name), ' '))) as 'Last Name',
I do not need the "MiddleNames" part and maybe this is not the most efficient way to solve it, but it works for me.
Got here from google, and came up with a slightly different solution that does handle names with more than two parts (up to 5 name parts, as would be created by space character). This sets the last_name column to everything to the right of the 'first name' (first space), it also sets full_name to the first name part. Perhaps backup your DB before running this :-) but here it is it worked for me:
UPDATE users SET
name_last =
CASE
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 1)) = LENGTH(full_name) THEN ''
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 2)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -1)
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 3)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -2)
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 4)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -3)
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 5)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -4)
WHEN LENGTH(SUBSTRING_INDEX(full_name, ' ', 6)) = LENGTH(full_name) THEN SUBSTRING_INDEX(del_name, ' ', -5)
ELSE ''
END,
full_name = SUBSTRING_INDEX(full_name, ' ', 1)
WHERE LENGTH(name_last) = 0 or LENGTH(name_last) is null or name_last = ''
SUBSTRING_INDEX didn't work for me in SQL 2018, so I used this:
declare #fullName varchar(50) = 'First Last1 Last2'
declare #first varchar(50)
declare #last varchar(50)
select #last = right(#fullName, len(#fullName)-charindex(' ',#fullName, 1)), #first = left(#fullName, (charindex(' ', #fullName, 1))-1);
Yields #first = 'First', #last = 'Last1 Last2'

SQL match first part of string and compare

I use Oracle and MySql, so if you have any answer in both codes please let me know,
Issue:
I have 2 columns in one table called: USers
Column#1= Names
Column#2= UCNames
This list contain names that are from different sources but partially match like:
Names
Alex Jones Marfex
UCNames
Alex Jonnes Mike Marfex
I want to compare both of the columns and find match based on the following attributes:
Search on the first 4 for letters and 4 last words and to store in new column called: verifiyed
Thanks
This gives you the first word in a string
Substring(Col,1,(Locate (' ',Col + ' ')-1)) First
This gives you the last word in a string
Reverse(Substring(Reverse(Col), 1, Locate(' ',Reverse(Col)) - 1)) Last
So your compare could be
Where
Substring(Col1,1,( Locate(' ',Col1 + ' ')-1))
= Substring(Col2,1,( Locate(' ',Col2 + ' ')-1))
And
Reverse(Substring(Reverse(Col1), 1, Locate(' ',Reverse(Col1)) - 1))
= Reverse(Substring(Reverse(Col2), 1, Locate(' ',Reverse(Col2)) - 1))
I went with words which seemed safer for what you are trying to do with just a bit more effort. If you do want to keep the 4 characters, just replace the Locate es with 4.
Based on the answer by #asantaballa , but using MySQL SUBSTRING_INDEX function :-
WHERE SUBSTRING_INDEX(Col1, ' ', 1) = SUBSTRING_INDEX(Col2, ' ', 1)
AND SUBSTRING_INDEX(Col1, ' ', -1) = SUBSTRING_INDEX(Col2, ' ', -1)
or to crudely check the first 4 characters and the last 4 words:-
WHERE SUBSTRING(Col1, 1, 4) = SUBSTRING(Col2, 1, 4)
AND SUBSTRING_INDEX(Col1, ' ', -4) = SUBSTRING_INDEX(Col2, ' ', -4)

MySQL Multiple lines string puts 0

I'm trying to insert a multiple line string into my MySQL db.
Example:
INSERT INTO `dressuurpaardje`.`Marks` (`markID`, `testID`, `markPosition`, `techinicalMark`, `directiveIdeas`, `maxMark`, `coefficient`, `overflow`)
VALUES (NULL, 1, 'M', 'Proceed in passage ' + CHAR(10) + CHAR(13) + ' Transition collected walk - passage', NULL, 10, NULL, NULL);
I use ' + CHAR(10) + CHAR(13) + ' with the intention to get a newline in the string. But this puts the string "0" in my db
Any suggestions?
Use '\n' in your query, and let the text interpreter add the line (depends what you use, but that's what I would recommend)
Use CONCAT(string1, CHAR(10), CHAR(13), string2), as mentionned also by Mazatwork.
Be aware that CHAR10 + CHAR13 is wrong. A line feed / carriage return is either:
chr10 or \n (unix)
chr13 + chr10 or \r\n (windows)

MSSQL to MYSQL using CASE WHEN THEN SUBSTRING & CHARINDEX

I am having some real difficulty converting the below MSSQL statement to produce the same results in MYSQL.
The MSSQL query is as follows:
SELECT Radius_AdslUser.Password, Radius_AdslIp.IpAdd, Route =
CASE WHEN Radius_AdslIP.Route IS NULL
THEN NULL
WHEN Radius_AdslIp.TotalIp = 8
THEN Radius_AdslIP.Ipadd + '/29 ' + SUBSTRING(Radius_AdslIp.Route, 10, Charindex(' ', Radius_AdslIp.Route) - 10) + ' 1'
WHEN Radius_AdslIp.TotalIp = 4
THEN Radius_AdslIP.Ipadd + '/30 ' + SUBSTRING(Radius_AdslIp.Route, 10, Charindex(' ', Radius_AdslIp.Route) - 10) + ' 1'
WHEN Radius_AdslIp.TotalIp = 16
THEN Radius_AdslIP.Ipadd + '/28 ' + SUBSTRING(Radius_AdslIp.Route, 10, Charindex(' ', Radius_AdslIp.Route) - 10) + ' 1'
END, AVPair =
CASE WHEN Radius_AdslUser.bandcap IS NULL
THEN NULL
ELSE 'throttle=' + Radius_AdslUser.bandcap
END, Radius_AdslIp.Subnet
FROM Radius_AdslUser,Radius_AdslIp
WHERE Username = 'username#test.tld'
AND Suspended = 0
AND Radius_AdslUser.IpAddId = Radius_AdslIp.IpAddId
Which produces the following result:
Password IpAdd Route AVPair Subnet
kmbjdatr 10.0.0.1 10.0.0.1/29 10.0.0.0 1 NULL 255.255.255.255
The format of the tables are as follows:
Radius_AdslIp
IpAddId IpAdd Subnet TotalIp UsableIp Route TypeId
944 10.0.0.1 255.255.255.255 8 6 ip:route=10.0.0.0 255.255.255.248 4
Radius_AdslUser
Username Password IpAddId
username#test.tld kmbjdatr 944
I have substituted CHARINDEX for LOCATE and have used CONCAT but am not having much luck.
For example:
WHEN Radius_AdslIp.TotalIp = 8 THEN Radius_AdslIp.Ipadd = CONCAT(Radius_AdslIp.Ipadd, '/29 ')
The table formats in MYSQL are identical.
Any help would be greatly appreciated.
Seems like you are not applying the CONCAT function correctly. Basically, a SQL Server expression like this:
column_name + 'constant string' + function_call() + #variable
would look like this in MySQL:
CONCAT(column_name, 'constant string', function_call(), #variable)
The particular wrong part in your excerpt seems to be Radius_AdslIp.Ipadd = (the one before CONCAT). Not sure what you meant by that, but in any event it's just not needed there.