MySQL Second (or third) Index Of in String - mysql

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

Related

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

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

Split string values separated by a semicolon using sProc in MySQL 8

I need split this string using stored Procedure in MySQL 8 version
"John;Elizabeth;Mark;Zagor;Annie;Lucy;Peter;Robin;Wilson;Tom;Bettie;Myriam;Frankie;Nick;Marilyn"
The string values are separated by a semicolon.
My sProc below.
The problem it's in output.
The first name splitted on this string it's Elizabeth and not John.
Where is it John?
All other names are present in output of sProc, only John is missing...
What am I doing wrong?
BEGIN
DECLARE tNameSeries LONGTEXT;
DECLARE t_tNameSeries LONGTEXT;
SET tNameSeries = "John;Elizabeth;Mark;Zagor;Annie;Lucy;Peter;Robin;Wilson;Tom;Bettie;Myriam;Frankie;Nick;Marilyn";
WHILE LOCATE(";",tNameSeries) > 0 DO
SET tNameSeries = REPLACE (tNameSeries, (SELECT LEFT(tNameSeries,LOCATE(";",tNameSeries))),'');
SET t_tNameSeries = SUBSTRING_INDEX(tNameSeries,";",1);
SELECT t_tNameSeries;
END WHILE;
END
update
Using ths edit sProc the output is only John
BEGIN
DECLARE tNameSeries LONGTEXT;
DECLARE t_tNameSeries LONGTEXT;
SET tNameSeries = "John;Elizabeth;Mark;Zagor;Annie;Lucy;Peter;Robin;Wilson;Tom;Bettie;Myriam;Frankie;Nick;Marilyn";
WHILE LOCATE(";",tNameSeries) > 0 DO
SET t_tNameSeries = SUBSTRING_INDEX(tNameSeries,";",1);
SET tNameSeries = REPLACE (t_tNameSeries, (SELECT LEFT(t_tNameSeries,LOCATE(";",t_tNameSeries))),'');
SELECT tNameSeries;
END WHILE;
END
SELECT *
FROM JSON_TABLE(
CONCAT(
'["',
REPLACE(
"John;Elizabeth;Mark;Zagor;Annie;Lucy;Peter;Robin;Wilson;Tom;Bettie;Myriam;Frankie;Nick;Marilyn",
';',
'","'
),
'"]'
),
'$[*]' COLUMNS (
id FOR ORDINALITY,
name VARCHAR(255) PATH '$'
)
) jsontable;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=546907fc5c00b7173fa73327fdd97638
Insert it into the SP if needed.
This works too:
set #names = 'John;Elizabeth;Mark;Zagor;Annie;Lucy;Peter;Robin;Wilson;Tom;Bettie;Myriam;Frankie;Nick;Marilyn';
select
substring_index(substring_index(#names,';',R),';',-1) W
from (select row_number() over () as R
from information_schema.tables) x
where x.R<=1+length(#names)-length(replace(#names,';',''));
see: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=5cc442be9da54d8cbcdbabc58ee37b65

Matching records from two tables

I have two Tables: ads_info and ads.
I want to match records from two tables.
SQL Schema for ads:
| id | title |
|----|-----------------------|
| 1 | This Dog is very nice |
SQL Schema for ads_info:
| id | infotext | tag |
|----|------------------------------|-----------|
| 1 | Dogs can eat a lot of things | dog, pets |
I want to check if the title of the Ads with id 1 has tags in ads_info. I have tried this:
SELECT * FROM `ads` where id = '1' UNION
SELECT * FROM `ads_info` where tag like '%ads.title%'
HERE IS SQL FIDDLE: LINK
Do you want a simple join?
select a.*, ai.tag,
(tag like concat('%', ads.title, '%')) as flag
from ads a join
ads_info ai
on ai.id = a.id;
The flag is, of course, false. It is rather hard to see situations where it would evaluate to true as you have expressed the logic.
Well you can do it this way : DEMO I am sure there are better ways and even this example can be better executed :) But it will maybe help...
First you create function for split and procedure for inserting those values in table(I have used here a answer from here LINK and corrected some small errors):
FUNCTION
CREATE FUNCTION SPLIT_STR(
x VARCHAR(255),
delim VARCHAR(12),
pos INT
)
RETURNS VARCHAR(255)
RETURN REPLACE(SUBSTRING(SUBSTRING_INDEX(x, delim, pos),
LENGTH(SUBSTRING_INDEX(x, delim, pos -1)) + 1),
delim, '');
PROCEDURE
CREATE PROCEDURE ABC(in fullstr VARCHAR(255))
BEGIN
DECLARE a int default 0;
DECLARE str VARCHAR(255);
simple_loop: LOOP
SET a=a+1;
SET str=SPLIT_STR(fullstr,",",a);
IF str='' THEN
LEAVE simple_loop;
END IF;
insert into my_temp_table values (str);
END LOOP simple_loop;
END;
I have created a table for this values:
create table my_temp_table (temp_columns varchar(100));
Called the procedure:
call ABC((select tag from ads_info));
And then you can use this:
Select * from ads B where exists
(select * from my_temp_table where
find_in_set(UPPER(trim(temp_columns)), replace(UPPER(B.TITLE), ' ', ',')) > 0 );
Or this:
SELECT * FROM ads, my_temp_table
WHERE find_in_set(UPPER(trim(temp_columns)), replace(UPPER(ads.TITLE), ' ', ',')) > 0 ;

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

SQL QUERY LIKE & IN TOGETHER

I have a column in table which has following values. Names are separed by comma..
ProjID Names
1 Adam , Babita Tripathy, Alex, Mihir , Farhad
2 SaravanaKumar, Shruthi, Arthi, Suneeth
I am passing input value to stored procedure to fetch values. The input value is multiple names. If input is (Arthi,SaravanaKumar) i need to get both the rows as result because ProjID 1 and 2 has one of the input names. How can i achive it. Please help..
Search Condition.
IF #Names<>''
SET #condition = #condition+' ProdType.NamesLIKE'''+'%'+RTRIM(#Names)+'%'' AND'
You can use a function to split he input string
IF EXISTS(SELECT * FROM sysobjects WHERE ID = OBJECT_ID('UF_CSVToTable'))
DROP FUNCTION UF_CSVToTable
GO
CREATE FUNCTION UF_CSVToTable
(
#psCSString VARCHAR(8000)
)
RETURNS #otTemp TABLE(sID VARCHAR(MAX))
AS
BEGIN
DECLARE #sTemp VARCHAR(10)
DECLARE #tTemp VARCHAR(10)
WHILE LEN(#psCSString) > 0
BEGIN
SET #sTemp = LEFT(#psCSString, ISNULL(NULLIF(CHARINDEX(',', #psCSString) - 1, -1),
LEN(#psCSString)))
SET #psCSString = SUBSTRING(#psCSString,ISNULL(NULLIF(CHARINDEX(',', #psCSString), 0),
LEN(#psCSString)) + 1, LEN(#psCSString))
INSERT INTO #otTemp(sID) VALUES (#sTemp)
END
RETURN
END
Go
It can be called like this.
select * from UF_CSVToTable('1,2,3,4,5,6,7,15,55,59,86')
SQL FIDDLE DEMO