SQL: how to split a stringSQL: how to split a string - mysql

I want to split a character string is part of the comma but the orca I try my code below it only returns me the index of the first comma and not the different strings fraction of the sentence
DELIMITER $$
create procedure separertext()
BEGIN
DECLARE text varchar (128);
DECLARE i varchar (10);
DECLARE j varchar(10);
DECLARE ind varchar(100);
DECLARE nom varchar (128);
set text = 'bonjour,daryle,manuella';
select LOCATE(',', text) as c;
SELECT SUBSTRING(text, 1, c) AS ExtractString;
END$$
DELIMITER ;
and here is the result I got
+------+
| c |
+------+
| 8 |
+------+`
`1 row in set (0.001 sec)

You might look at the SUBSTRING_INDEX function of MySQL for your procedure.
Here is a good tutorial to help you with your Problem.

You need an iterative approach to extract an unknown number of substrings from a string. In SQL this is done with recursive queries (available since MySQL 8.0).
I am using REGEXP_SUBSTR here for convenience. The same can be done with a combination of SUBSTRING and LOCATE.
with recursive substrings(str, substr, pos) as
(
select str, substring_index(str, ',', 1), 1
from mytable
union all
select str, regexp_substr(str, '[^,]+', 1, pos + 1), pos + 1
from substrings
where regexp_substr(str, '[^,]+', 1, pos + 1) is not null
)
select *
from substrings
order by str, pos;
Demo: https://dbfiddle.uk/yRv4fUD1

Related

Getting a value from a JSON string in purely MySQL

I'm looking for a single query that's purely MySQL. The goal of this query is to utilize things such as SUBSTRING_INDEX, CONCAT, or whatever it needs to, in order to find a value in a string.
Let's say that the string looks something like this:
{"name":34,"otherName":55,"moreNames":12,"target":26,"hello":56,"hi":26,"asd":552,"p":3722,"bestName":11,"cc":6,"dd":10,}
My goal is to get the value of target, in this case, 26. However, "target":26 might not always be in that location in the string. Neither would any of the other properties. On top of that, the value might not always be 26. I need some way to check what number comes after "target": but before the , after "target":. Is there any way of doing this?
This one ?
create table sandbox (id integer, jsoncolumn varchar(255));
insert into sandbox values (1,'{"name":34,"otherName":55,"moreNames":12,"target":26,"hello":56,"hi":26,"asd":552,"p":3722,"bestName":11,"cc":6,"dd":10}');
mysql root#localhost:sandbox> SELECT jsoncolumn->'$.target' from sandbox;
+--------------------------+
| jsoncolumn->'$.target' |
|--------------------------|
| 26 |
+--------------------------+
https://dev.mysql.com/doc/refman/5.7/en/json-search-functions.html
Please try this function to get value from JSON string in MYSQL
DROP FUNCTION IF EXISTS CAP_FIRST_CHAR;
DELIMITER $$
CREATE FUNCTION getValueFromJsonSring(jsonStr VARCHAR(250), getKey VARCHAR(250))
RETURNS VARCHAR(250) deterministic
BEGIN
DECLARE output VARCHAR(250); -- Holds the final value.
DECLARE data VARCHAR(250); -- Holds the exctracted value from JSON
SET getKey=CONCAT('"',getKey,'"');
SET data= TRIM(LEADING ':' FROM
substring_index(
substring_index(
substring_index(
substring_index(
SUBSTRING(jsonStr, 2, LENGTH(jsonStr)-2)
, getKey , '2'),
getKey,
-1
)
, ',', '1'),
',',
-1
)
);
SET output =SUBSTRING(data, 2, LENGTH(data)-2);
RETURN output;
END;
$$
DELIMITER ;
SELECT getValueFromJsonSring('{"amount":"400.34","departmentId":"7","date":"2017-06-02","PONumber":"0000064873","vendor":"44"}',"departmentId");

Select Next 10 Characters Following Specific String

I'm trying to figure out how to create a single MySQL query that will allow me to display only the next 10 characters following the string "filter" in the Message field. The string "filter" appears at various positions in each record, so I can't use a position filter.
I've been trying to use something like like what I have below, however I've been unable to get the correct query.
SELECT RIGHT(Message,LOCATE('filter',Message) - 10) FROM table
The Message field records within the table looks like:
QgySSW8fwD25iQ.filter0019p3las1-31205-59C3D
6t2fJw.filter0010p3las1-9745-59
filter0025p3las1-13130-59C3D317
And I'm looking for them to look like this after the query:
0019p3las1
0010p3las1
0025p3las1
Any help is greatly appreciated.
Use a combination of LOCATE() within SUBSTRING(). See this SQL Fiddle
CREATE TABLE Table1
(`message` varchar(200))
;
INSERT INTO Table1
(`message`)
VALUES
('QgySSW8fwD25iQ.filter0019p3las1-31205-59C3D'),
('6t2fJw.filter0010p3las1-9745-59'),
('filter0025p3las1-13130-59C3D317')
;
Query 1:
select
SUBSTRING(message,LOCATE('filter',Message)+6,10)
from table1
Note that the +6 is to offset for the length of "filter" because LOCATE finds the position of the "f" and you then need to add 6 for the other characters "ilter". Once that number is determined then just get the next 10 characters.
Results:
| SUBSTRING(message,LOCATE('filter',Message)+6,10) |
|--------------------------------------------------|
| 0019p3las1 |
| 0010p3las1 |
| 0025p3las1 |
See SQLFiddle.
Result table structure
Create table resulttbl (
id int(6) primary key auto_increment ,
resultFIlter varchar(1000)
);
Function to split string
CREATE FUNCTION strSplit(x VARCHAR(65000), delim VARCHAR(12), pos INTEGER)
RETURNS VARCHAR(65000)
BEGIN
DECLARE output VARCHAR(65000);
SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos)
, LENGTH(SUBSTRING_INDEX(x, delim, pos - 1)) + 1)
, delim
, '');
IF output = '' THEN SET output = null; END IF;
RETURN output;
END;
Stored procedure to split and insert into result table
CREATE PROCEDURE FilterTable()
BEGIN
DECLARE i INTEGER;
DECLARE endpos INTEGER;
DECLARE fullstr VARCHAR(1000);
DECLARE result VARCHAR(1000);
SET fullstr = 'QgySSW8fwD25iQ.filter0019p3las1-31205-59C3D 6t2fJw.filter0010p3las1-9745-59 filter0025p3las1-13130-59C3D317';
SET i = 2;
SET endpos=LENGTH(fullstr) - LENGTH(REPLACE(fullstr, 'filter', '')) ;
delete from resulttbl;
REPEAT
SET result=strSplit(fullstr, 'filter', i);
IF result IS NOT NULL THEN
SET result=LEFT(result,10);
INSERT INTO resulttbl (resultFIlter) values(result);
END IF;
SET i = i + 1;
UNTIL i >= endpos
END REPEAT;
END ;
Call the procedure using the statement CALL FilterTable().
Now the result of your procedure is available on the table resulttbl.
You can get the values from that table using select statement as SELECT * from resulttbl.
Result
id resultFIlter
1 0019p3las1
2 0010p3las1
3 0025p3las1

Mysql: Finding longest character sequence in a string

In mySQL, how can I find the length of the longest sequence of a given character? For example, in the following string
1325******2h3n***3k2n*
If I were looking for the * character, the result should be 6 because the chain of 6 * characters is the longest present in the string.
You can use instr and and generated table with UNION to get it.
-- This query can find up to 10. If more need, need to update the `UNION`.
select max((instr('1325*****2h3n***3k2n*',repeat('*', times)) != 0) * times ) longest_seq
from (select 1 times union select 2 union select 3 union select 4 union select 5
union select 6 union select 7 union select 8 union select 9 union select 10) t;
Demo:
mysql> select max((instr('1325*****2h3n***3k2n*',repeat('*', times)) != 0) * times ) longest_seq
-> from (select 1 times union select 2 union select 3 union select 4 union select 5
-> union select 6 union select 7 union select 8 union select 9 union select 10) t;
+-------------+
| longest_seq |
+-------------+
| 5 |
+-------------+
1 row in set (0.01 sec)
what your looking for is basically the length of the longest substring,
you can find the algorithm for it here
Trying to achieve this with a query would not be such a good idea,
I suggest, using a stored procedure instead.
Dylan Su's solution is clever and works well if you know the maximum number of characters is small or don't want the overhead of building a function.
On the other hand one of the following function definitions will work regardless of character length without having to add new UNION statements indefinitely.
This function loops over each of the characters in the string, and if they match the repeat character, increments a length counter. It then returns the max length.
DELIMITER //
CREATE FUNCTION LONGEST_CHARACTER_SEQUENCE(input VARCHAR(255), repeat_character CHAR(1))
RETURNS TINYINT UNSIGNED DETERMINISTIC NO SQL
BEGIN
DECLARE max_length TINYINT UNSIGNED DEFAULT 0;
DECLARE length TINYINT UNSIGNED DEFAULT 0;
DECLARE in_sequence BOOLEAN DEFAULT 0;
DECLARE position INT DEFAULT 1;
WHILE position <= LENGTH(input) DO
IF SUBSTRING(input, position, 1) = repeat_character THEN
IF in_sequence THEN
SET length = length + 1;
ELSE
SET length = 1;
END IF;
IF length > max_length THEN
SET max_length = length;
END IF;
SET in_sequence = 1;
ELSE
SET in_sequence = 0;
END IF;
SET position = position + 1;
END WHILE;
RETURN max_length;
END//
DELIMITER ;
SELECT LONGEST_CHARACTER_SEQUENCE('1325******2h3n***3k2n*', '*');
-- Returns: 6
Inspired by Dylan Su's answer, this function increments a length counter until INSTR no longer returns true. I think it's simpler.
DELIMITER //
CREATE FUNCTION LONGEST_CHARACTER_SEQUENCE(input VARCHAR(255), repeat_character CHAR(1))
RETURNS TINYINT UNSIGNED DETERMINISTIC NO SQL
BEGIN
DECLARE length TINYINT UNSIGNED DEFAULT 0;
WHILE INSTR(input, REPEAT(repeat_character, length + 1)) DO
SET length = length + 1;
END WHILE;
RETURN length;
END//
DELIMITER ;
SELECT LONGEST_CHARACTER_SEQUENCE('1325******2h3n***3k2n*', '*');
-- Also returns: 6

MySQL Second (or third) Index Of in String

What would be the simplest way to locate the index of the third space in a string.
My goal is to get CCC out of this space separated list: AAAA BBBB CCCC DDDD EEE. where A and B and D are fixed length, and C is variable length, E F G are optional.
In Java I would use indexof, with a starting point of 10 and that would get me the third space, but it seems that I cannot do that in MySQL, so I thought maybe I could find a 'third index of' function?
You would want to use SUBSTRING_INDEX function like this
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(field, ' ', 3), ' ', -1)
FROM table
The inner function call would get you to AAAA BBBB CCCC while the outer function call would pare that down to just CCCC.
Generally you can select the nth word in a string using:
SET #N = 3; -- 3rd word
SET #delimiter = ' ';
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(words, #delimiter, #N), #delimiter, -1)
FROM
my_table
DROP FUNCTION IF EXISTS `Find_string_by_position`$$
CREATE DEFINER=`root`#`localhost` FUNCTION
`Find_string_by_position`(str VARCHAR(255), delimeter VARCHAR(255),pos INT(2)) RETURNS VARCHAR(255) CHARSET utf8mb4 BEGIN
DECLARE s VARCHAR(255);
DECLARE d VARCHAR(255);
DECLARE p INT DEFAULT 1;
DECLARE val VARCHAR(255);
SET s = LCASE(str);
SET d = delimeter;
SET p = pos;
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(s,d,p),d,-1) INTO #val;
RETURN #val;
END$$
DELIMITER ;
use below query to find any random id from table after group by.
Here id is the autoincrement_id.
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(GROUP_CONCAT(id),",",FLOOR(RAND()*COUNT(DISTINCT id))+1),",",-1) AS random_id FROM tableName GROUP BY groupbyColumn
Id
Name
Department
1
Amit Kumar Sharma
Computer Science
*You can extract third string by simple query
Query :-
SELECT SUBSTRING_INDEX(Name, ' ', -1) as last_name FROM table_name
Output :-
Sharma

mysql get ascii code dump for string

In MySQL, is there a way in a simple SELECT to obtain a sequence of ASCII code/code points for each character in a varchar value? I'm more familiar with Oracle, which has the DUMP function that can be used for this.
For example, select some_function('abcd') would return something like 96,97,98,99?
This is about the closest equivalent I'm aware of in MySQL:
mysql> select hex('abcd');
+-------------+
| hex('abcd') |
+-------------+
| 61626364 |
+-------------+
1 row in set (0.00 sec)
I don't know of a mysql_function that will do that, but you can take the string in php, convert to an array, then take the ordinal of the character.
$char_value_array = {};
foreach($mysql_fetched_str as $char)
array_push($char_value_array, ord($char)
You can create a function like this:
CREATE FUNCTION dump (s CHAR(20)) RETURNS CHAR(50) DETERMINISTIC
BEGIN
DECLARE result CHAR(50);
DECLARE i INT;
DECLARE l INT;
SET result = ASCII(SUBSTRING(s,1,1));
SET l = LENGTH(s);
SET i = 2;
WHILE (i <= l) DO
SET result = CONCAT(result, ',', ASCII(SUBSTRING(s,i,1)));
SET i = i + 1;
END WHILE;
RETURN result;
END;
And then use it in the SELECT:
SELECT dump('abcd') FROM test LIMIT 1
Increase CHAR(20) and CHAR(50) definitions if you need to use it with longer strings.