How to select string between characters? - mysql

I made this table:
Table (Websites)
WebsiteID | WebsiteName
2324442 'http://www.samsung.com/us/'
2342343 'https://www.microsoft.com/en-au/windows/'
3242343 'http://www.apple.com/au/iphone/'
And I want to be able to SELECT the domain names from this table.
Something like this:
WebsiteName
'www.samsung.com'
'www.microsoft.com'
'www.apple.com'
Is there a string method I can use for this? Like splitting the string between // and /.

You can use SUBSTRING_INDEX() :
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(websiteName, '//', -1),
'/', 1)
FROM table

You can even use the following:
SELECT WebsiteID , WebsiteName
(CHARINDEX ( '//', WebsiteName, 1 ) + 1), -- Position of the double slashes
CHARINDEX( '/', REVERSE (WebsiteName ), 1), -- Position of the last single slash
SUBSTRING(WebsiteName, (CHARINDEX ( '//' , WebsiteName, 1 ) + 2), CHARINDEX( '/', REVERSE (WebsiteName ), 1) ) -- Final string
FROM Table

Related

MySQL: Extract regexp value from query

I would need to get value from given regexp.
For example:
> :"postalCode";s:4:"3150";
Is there any way I can extract 3150, from this part of column value. Column value stored serialized objects, so postalCode variable can be null type, that way I should check if positive integer follows ;s:POSITIVE_INT:"postalCodeValue
Use SUBSTRING_INDEX:
SELECT
SUBSTRING(SUBSTRING_INDEX(col, '"', -2), 1,
INSTR(SUBSTRING_INDEX(col, '"', -2), '"') - 1) AS num
FROM yourTable;
This query will extract the last quoted number in your string.
Demo
avoiding regexp you could use some string function eg:
SELECT LENGTH(':"postalCode";s:4:"3150"') - LOCATE(':', REVERSE(':"postalCode";s:4:"3150"'))+1
from dual ;
or
SELECT LENGTH(col_name) - LOCATE(':', REVERSE(col_name))+1
from my_table ;
It also work with 2 times SUBSTRING_INDEX
SELECT
SUBSTRING_INDEX (SUBSTRING_INDEX( ':"postalCode";s:4:"3150";', '"',-2) , '"', 1);

Replacing an string on a field via MySQL

I have the following field (which is a string) of one of my tables:
'[{"id":"6","value":["http://www.google.com","http://www.google.com","new"]},
{"id":"7","value":"Reuters"},
{"id":"20","value":"2017/03/17"}]'`
As you can see, the last part, the one with id=20 has a date on it, 2017/03/17.
Can someone tell me how can I update that field so I can get the output 2017-03-17?
My desired output after the update would be:
'[{"id":"6","value":["http://www.google.com","http://www.google.com","new"]},
{"id":"7","value":"Reuters"},
{"id":"20","value":"2017-03-17"}]'`
If I use:
UPDATE mytable
SET myfield = replace(myfield , '/', '-');
It removes the / of the links, and I want to mantain them.
PS: The ids of the fields are always the same (the one for the date is always 20 for example) the only thing that changes are the values.
you can do it with a query like this:
UPDATE mytable
SET myfield = CONCAT (
SUBSTRING_INDEX(myfield, '"id":"20","value":', 1)
, '"id":"20","value":',
, REPLACE (SUBSTRING_INDEX(myfield, '"id":"20","value":', -1),'/','-')
)
WHERE ....:
sample
mysql> SELECT
-> CONCAT (
-> SUBSTRING_INDEX('[{"id":"6","value":["http://www.google.com","http://www.google.com","new"]},
'> {"id":"7","value":"Reuters"},
'> {"id":"20","value":"2017/03/17"}]', '"id":"20","value":', 1),
-> '"id":"20","value":',
-> REPLACE (SUBSTRING_INDEX('[{"id":"6","value":["http://www.google.com","http://www.google.com","new"]},
'> {"id":"7","value":"Reuters"},
'> {"id":"20","value":"2017/03/17"}]', '"id":"20","value":', -1),'/','-')
-> ) AS result;
+------------------------------------------------------------------------------------------------------------------------------------------------+
| result |
+------------------------------------------------------------------------------------------------------------------------------------------------+
| [{"id":"6","value":["http://www.google.com","http://www.google.com","new"]},
{"id":"7","value":"Reuters"},
{"id":"20","value":"2017-03-17"}] |
+------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0,00 sec)
mysql>
Maybe there is a better way, But you can :
split the string into rows using { as separator
find the row with "ID=20"
do the replace
join all rows back together using GROUP_CONCAT
DEMO
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(T.json, '{', numbers.n), '{', -1) name,
CASE WHEN INSTR(SUBSTRING_INDEX(SUBSTRING_INDEX(T.json, '{', numbers.n), '{', -1), '"id":"20"') > 0
THEN REPLACE(SUBSTRING_INDEX(SUBSTRING_INDEX(T.json, '{', numbers.n), '{', -1), '/', '-')
ELSE SUBSTRING_INDEX(SUBSTRING_INDEX(T.json, '{', numbers.n), '{', -1)
END as result
FROM
(select 1 n union all
select 2 union all select 3 union all
select 4 union all select 5) numbers
JOIN (
SELECT '[{"id":"6","value":["http://www.google.com","http://www.google.com","new"]},
{"id":"7","value":"Reuters"},
{"id":"20","value":"2017/03/17"}]' as json
) T
on CHAR_LENGTH(T.json)
-CHAR_LENGTH(REPLACE(T.json, '{', ''))>=numbers.n-1
order by
n
OUTPUT
OPTION 2
SELECT SUBSTRING(json, 1, pos_begin - 1 ) as side_left,
REPLACE(SUBSTRING(json, pos_begin, pos_end - pos_begin + 1), '/', '-') as side_middle,
SUBSTRING(json, pos_end + 1, LENGTH(json)) as side_end
FROM (
SELECT LOCATE('{"id":"20"', json) as pos_begin,
LOCATE('}', json, LOCATE('{"id":"20"', json)) as pos_end,
T.json
FROM (
SELECT '[{"id":"6","value":["http://www.google.com","http://www.google.com","new"]},
{"id":"7","value":"Reuters"},
{"id":"20","value":"2017/03/17"}]' as json
) T
) S
;
OUTPUT

Mysql replace not all string?

I have column(pro_doc) string like [1,2,11,]
UPDATE product SET prod_doc = REPLACE(prod_doc, '1,' , '') WHERE prod_id = 2
The result is 2,1
I want become 2,11,
I just want replace first 1, not all 1,
Have any solution?
Thanks a lot...
Use SUBSTRING_INDEX.
Find the total occurence of , and use negative of that as the last argument of the SUBSTRING_INDEX function.
UPDATE product
SET prod_doc =
SUBSTRING_INDEX(
prod_doc, ',', -(
ROUND(
(
LENGTH(prod_doc) - LENGTH(REPLACE(prod_doc, ',', ''))
) / LENGTH(','))
)
)
WHERE prod_id = 2;
SQL Fiddle Demo

mysql split string [duplicate]

I have a column that has comma separated data:
1,2,3
3,2,1
4,5,6
5,5,5
I'm trying to run a search that would query each value of the CSV string individually.
0<first<5 and 1<second<3 and 2<third<4
I get that I could return all queries and split it myself and compare it myself. I'm curious if there is a way to do this so MySQL does that processing work.
Thanks!
Use
substring_index(`column`,',',1) ==> first value
substring_index(substring_index(`column`,',',-2),',',1)=> second value
substring_index(substring_index(`column`,',',-1),',',1)=> third value
in your where clause.
SELECT * FROM `table`
WHERE
substring_index(`column`,',',1)<0
AND
substring_index(`column`,',',1)>5
It seems to work:
substring_index ( substring_index ( context,',',1 ), ',', -1)
substring_index ( substring_index ( context,',',2 ), ',', -1)
substring_index ( substring_index ( context,',',3 ), ',', -1)
substring_index ( substring_index ( context,',',4 ), ',', -1)
it means 1st value, 2nd, 3rd, etc.
Explanation:
The inner substring_index returns the first n values that are comma separated. So if your original string is "34,7,23,89", substring_index( context,',', 3) returns "34,7,23".
The outer substring_index takes the value returned by the inner substring_index and the -1 allows you to take the last value. So you get "23" from the "34,7,23".
Instead of -1 if you specify -2, you'll get "7,23", because it took the last two values.
Example:
select * from MyTable where substring_index(substring_index(prices,',',1),',',-1)=3382;
Here, prices is the name of a column in MyTable.
Usually substring_index does what you want:
mysql> select substring_index("foo#gmail.com","#",-1);
+-----------------------------------------+
| substring_index("foo#gmail.com","#",-1) |
+-----------------------------------------+
| gmail.com |
+-----------------------------------------+
1 row in set (0.00 sec)
You may get what you want by using the MySQL REGEXP or LIKE.
See the MySQL Docs on Pattern Matching
As an addendum to this, I've strings of the form:
Some words 303
where I'd like to split off the numerical part from the tail of the string.
This seems to point to a possible solution:
http://lists.mysql.com/mysql/222421
The problem however, is that you only get the answer "yes, it matches", and not the start index of the regexp match.
Here is another variant I posted on related question. The REGEX check to see if you are out of bounds is useful, so for a table column you would put it in the where clause.
SET #Array = 'one,two,three,four';
SET #ArrayIndex = 2;
SELECT CASE
WHEN #Array REGEXP CONCAT('((,).*){',#ArrayIndex,'}')
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(#Array,',',#ArrayIndex+1),',',-1)
ELSE NULL
END AS Result;
SUBSTRING_INDEX(string, delim, n) returns the first n
SUBSTRING_INDEX(string, delim, -1) returns the last only
REGEXP '((delim).*){n}' checks if there are n delimiters (i.e. you are in bounds)
Building on #Oleksiy's answer, here is one that can work with strings of variable segment lengths (within reasonable limits), for example comma-separated addresses:
SELECT substring_index ( substring_index ( address,',',1 ), ',', -1) AS address_line_1,
IF(address_parts > 1, substring_index ( substring_index ( address,',',2 ), ',', -1), '') AS address_line_2,
IF(address_parts > 2, substring_index ( substring_index ( address,',',3 ), ',', -1), '') AS address_line_3,
IF(address_parts > 3, substring_index ( substring_index ( address,',',4 ), ',', -1), '') AS address_line_4,
IF(address_parts > 4, substring_index ( substring_index ( address,',',5 ), ',', -1), '') AS address_line_5
FROM (
SELECT address, LENGTH(address) - LENGTH(REPLACE(address, ',', '')) AS address_parts
FROM mytable
) AS addresses
It's working..
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(
SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(col,'1', 1), '2', 1), '3', 1), '4', 1), '5', 1), '6', 1)
, '7', 1), '8', 1), '9', 1), '0', 1) as new_col
FROM table_name group by new_col;

Can MySQL split a column?

I have a column that has comma separated data:
1,2,3
3,2,1
4,5,6
5,5,5
I'm trying to run a search that would query each value of the CSV string individually.
0<first<5 and 1<second<3 and 2<third<4
I get that I could return all queries and split it myself and compare it myself. I'm curious if there is a way to do this so MySQL does that processing work.
Thanks!
Use
substring_index(`column`,',',1) ==> first value
substring_index(substring_index(`column`,',',-2),',',1)=> second value
substring_index(substring_index(`column`,',',-1),',',1)=> third value
in your where clause.
SELECT * FROM `table`
WHERE
substring_index(`column`,',',1)<0
AND
substring_index(`column`,',',1)>5
It seems to work:
substring_index ( substring_index ( context,',',1 ), ',', -1)
substring_index ( substring_index ( context,',',2 ), ',', -1)
substring_index ( substring_index ( context,',',3 ), ',', -1)
substring_index ( substring_index ( context,',',4 ), ',', -1)
it means 1st value, 2nd, 3rd, etc.
Explanation:
The inner substring_index returns the first n values that are comma separated. So if your original string is "34,7,23,89", substring_index( context,',', 3) returns "34,7,23".
The outer substring_index takes the value returned by the inner substring_index and the -1 allows you to take the last value. So you get "23" from the "34,7,23".
Instead of -1 if you specify -2, you'll get "7,23", because it took the last two values.
Example:
select * from MyTable where substring_index(substring_index(prices,',',1),',',-1)=3382;
Here, prices is the name of a column in MyTable.
Usually substring_index does what you want:
mysql> select substring_index("foo#gmail.com","#",-1);
+-----------------------------------------+
| substring_index("foo#gmail.com","#",-1) |
+-----------------------------------------+
| gmail.com |
+-----------------------------------------+
1 row in set (0.00 sec)
You may get what you want by using the MySQL REGEXP or LIKE.
See the MySQL Docs on Pattern Matching
As an addendum to this, I've strings of the form:
Some words 303
where I'd like to split off the numerical part from the tail of the string.
This seems to point to a possible solution:
http://lists.mysql.com/mysql/222421
The problem however, is that you only get the answer "yes, it matches", and not the start index of the regexp match.
Here is another variant I posted on related question. The REGEX check to see if you are out of bounds is useful, so for a table column you would put it in the where clause.
SET #Array = 'one,two,three,four';
SET #ArrayIndex = 2;
SELECT CASE
WHEN #Array REGEXP CONCAT('((,).*){',#ArrayIndex,'}')
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(#Array,',',#ArrayIndex+1),',',-1)
ELSE NULL
END AS Result;
SUBSTRING_INDEX(string, delim, n) returns the first n
SUBSTRING_INDEX(string, delim, -1) returns the last only
REGEXP '((delim).*){n}' checks if there are n delimiters (i.e. you are in bounds)
Building on #Oleksiy's answer, here is one that can work with strings of variable segment lengths (within reasonable limits), for example comma-separated addresses:
SELECT substring_index ( substring_index ( address,',',1 ), ',', -1) AS address_line_1,
IF(address_parts > 1, substring_index ( substring_index ( address,',',2 ), ',', -1), '') AS address_line_2,
IF(address_parts > 2, substring_index ( substring_index ( address,',',3 ), ',', -1), '') AS address_line_3,
IF(address_parts > 3, substring_index ( substring_index ( address,',',4 ), ',', -1), '') AS address_line_4,
IF(address_parts > 4, substring_index ( substring_index ( address,',',5 ), ',', -1), '') AS address_line_5
FROM (
SELECT address, LENGTH(address) - LENGTH(REPLACE(address, ',', '')) AS address_parts
FROM mytable
) AS addresses
It's working..
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(
SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(col,'1', 1), '2', 1), '3', 1), '4', 1), '5', 1), '6', 1)
, '7', 1), '8', 1), '9', 1), '0', 1) as new_col
FROM table_name group by new_col;