How to get initials from fullname in MySQL? - mysql

I have a simple table:
id | fullname
---------------------------
1 | Ivanov Ivan Ivanovich
---------------------------
2 | Petrov Petr Petrovich
---------------------------
3 | Alym kyzy Ainura
I need transform them into something like this:
id | name_initials
--------------------
1 | Ivanov I. I.
--------------------
2 | Petrov P. P.
--------------------
3 | Alym k. A.
I can easily make it via PHP, but MySQL is about data manipulation. I think, it might (and MUST) be done with DBMS only.
How can it be done via pure SQL?
Should I write stored function for this, or is there any shorter way?
Regards.

You could use a query like this:
SELECT
fullname,
CONCAT_WS(' ',
SUBSTRING_INDEX(fullname, ' ', 1),
CASE WHEN LENGTH(fullname)-LENGTH(REPLACE(fullname,' ',''))>2 THEN
CONCAT(LEFT(SUBSTRING_INDEX(fullname, ' ', -3), 1), '.')
END,
CASE WHEN LENGTH(fullname)-LENGTH(REPLACE(fullname,' ',''))>1 THEN
CONCAT(LEFT(SUBSTRING_INDEX(fullname, ' ', -2), 1), '.')
END,
CASE WHEN LENGTH(fullname)-LENGTH(REPLACE(fullname,' ',''))>0 THEN
CONCAT(LEFT(SUBSTRING_INDEX(fullname, ' ', -1), 1), '.')
END) shortname
FROM
Names
Please see fiddle here. This query will support at maximum four names.

Solved with stored function:
CREATE FUNCTION `getNameInitials`(`fullname` VARCHAR(70))
RETURNS VARCHAR(70)
DETERMINISTIC
BEGIN
DECLARE `result` VARCHAR(70) DEFAULT '';
DECLARE `position` TINYINT;
DECLARE `separator` VARCHAR(1) DEFAULT ' ';
DECLARE `append` VARCHAR(1) DEFAULT '.';
DECLARE `buffer` VARCHAR(10);
SET `fullname` = CONCAT(TRIM(`fullname`), `separator`);
SET `position` = LOCATE(`separator`, `fullname`);
IF NOT `position`
THEN RETURN TRIM(`fullname`);
END IF;
SET `result` = LEFT(`fullname`, `position` - 1);
cycle: LOOP
SET `fullname` = SUBSTR(`fullname`, `position` + 1);
SET `position` = LOCATE(`separator`, `fullname`);
IF NOT `position` OR NOT LENGTH(`fullname`)
THEN LEAVE cycle;
END IF;
SET `buffer` = CONCAT(LEFT(`fullname`, 1), `append`);
SET `result` = CONCAT_WS(`separator`, `result`, `buffer`);
END LOOP cycle;
RETURN `result`;
END
Checked with:
SELECT
getNameInitials(`fullname`) as `name`
FROM
(
SELECT
'Ivanov Ivan Ivanovich' as `fullname`
UNION ALL
SELECT 'Alym kyzy Ainura'
) `sub`;
And got following result:
'Ivanov I. I.'
'Alym k. A.'

CREATE DEFINER=`root`#`localhost` FUNCTION `getNameInitials`(`fullname` VARCHAR(500), `separator` VARCHAR(1)) RETURNS varchar(70) CHARSET latin1
DETERMINISTIC
BEGIN
DECLARE `result` VARCHAR(500) DEFAULT '';
DECLARE `position` TINYINT;
SET `fullname` = TRIM(`fullname`);
SET `position` = LOCATE(`separator`, `fullname`);
IF NOT `position`
THEN RETURN LEFT(`fullname`,1);
END IF;
SET `fullname` = CONCAT(`fullname`,`separator`);
SET `result` = LEFT(`fullname`, 1);
cycle: LOOP
SET `fullname` = SUBSTR(`fullname`, `position` + 1);
SET `position` = LOCATE(`separator`, `fullname`);
IF NOT `position` OR NOT LENGTH(`fullname`)
THEN LEAVE cycle;
END IF;
SET `result` = CONCAT(`result`,LEFT(`fullname`, 1));
-- SET `result` = CONCAT_WS(`separator`, `result`, `buffer`);
END LOOP cycle;
RETURN upper(`result`);
END
1.Execute this function in mysql. 2.this will create a function. Now you can use this function anywhere you want.
SELECT `getNameInitials`('Kaleem Ul Hassan', ' ') AS `NameInitials`;
The above getNameInitails first parameter is string you want to filter and second is the spectator character on which you want to separate you string. 4. In above example 'Kaleem Ul Hassan' is name and i want to get initials and my separator is space ' '.

Related

Is there a MySQL equivalent for Translate() in Oracle

I am retrieving some password values from MySQL table in Hibernate and replace that with other strings in MySQL. I understand that there is translate() in Oracle to do the replacement but I haven't found any of the same in MySQL.
Would there be any alternate solution other than Replace() in MySQL or any libraries that can be used for the same?
Till now there is no equivalent of Oracle's TRANSLATE() function in MySQL. However, you can achieve the desired results by using nested REPLACE() functions.
Adding an example -
Oracle query -
SELECT TRANSLATE('Vikas#Bharti-Infy', '#-', '_.') FROM dual;
Vikas_Bharti.Infy
The equivalent MySQL query will be -
SELECT REPLACE(REPLACE('Vikas#Bharti-Infy', '#', '_'),'-','.');
Vikas_Bharti.Infy
You could create one like this:
CREATE FUNCTION `translate`(subject varchar(255), what varchar(255), replace_to varchar(255)) RETURNS varchar(255)
begin
declare c int unsigned default 0;
declare result varchar(255);
set result = subject;
while c <= length(subject) do
set result = replace(result, mid(what, c, 1), mid(replace_to, c, 1) );
set c=c+1;
end while;
return result;
end
Then use:
mysql> select translate('(123) 1234-1234', '( )-','.,.,');
+---------------------------------------------+
| translate('(123) 1234-1234', '( )-','.,.,') |
+---------------------------------------------+
| .123.,1234,1234 |
+---------------------------------------------+
1 row in set (0.00 sec)
I tweaked Flavio's answer a little bit, the following function seems to work for me.
CREATE FUNCTION `translate` (
tar VARCHAR (255),
ori VARCHAR (255),
rpl VARCHAR (255)
) RETURNS VARCHAR (255) CHARSET utf8mb4 DETERMINISTIC BEGIN
DECLARE i INT UNSIGNED DEFAULT 0;
DECLARE cur_char CHAR (1);
DECLARE ori_idx INT UNSIGNED;
DECLARE result VARCHAR (255);
SET result = '';
WHILE i <= length(tar) DO
SET cur_char = mid(tar, i, 1);
SET ori_idx = INSTR(ori, cur_char);
SET result = concat(
result,
REPLACE(
cur_char,
mid(ori, ori_idx, 1),
mid(rpl, ori_idx, 1)
));
SET i = i + 1;
END WHILE;
RETURN result;
END
Tested with the following example:
mysql> SET #map_src = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
Query OK, 0 rows affected (0.00 sec)
mysql> SET #map_des = 'nrgzujmaqbetylxwkdohpfvcisNRGZUJMAQBETYLXWKDOHPFVCIS2014587639';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT translate('https://456.HELLO.world', #map_src, #map_des) as f1;
+-------------------------+
| f1 |
+-------------------------+
| ahhwo://458.AUTTX.vxdtz |
+-------------------------+
1 row in set (0.00 sec)
delimiter //
drop function if exists my_translate_fx //
create function my_translate_fx (p_str varchar(1024), p_ori varchar(1024), p_rep varchar(1024))
-- Replace characters p_ori with corresponding characters p_rep in string p_str
returns varchar(1024)
begin
declare l_ori varchar(1024) default ifnull(p_ori,'') ;
declare l_rep varchar(1024) default ifnull(p_rep,'') ;
declare l_len_ori int unsigned default ifnull(length(p_ori),0) ;
declare l_len_rep int unsigned default ifnull(length(p_rep),0) ;
declare l_res varchar(1024) default p_str ;
declare l_last_rep_chr varchar(6) default '' ;
declare l_pos_ori int unsigned default 1;
-- No change if no original char to replace
if l_len_ori < 1 then
return l_res ;
end if;
-- Replacement string p_rep to be same size as p_ori, when p_rep is not null
-- Complete replacement string repeating the last char in p_rep, eg. ' '
if l_len_rep > 0 then
set l_last_rep_chr := substr( l_rep ,l_len_rep,1) ;
while l_len_rep < l_len_ori do
set l_len_rep := l_len_rep + 1 ;
set l_rep := concat( l_rep, l_last_rep_chr );
end while ;
end if;
while l_pos_ori <= l_len_ori do
set l_res = replace(l_res, substr(l_ori, l_pos_ori, 1), substr(l_rep, l_pos_ori, 1) );
set l_pos_ori = l_pos_ori + 1;
end while;
return l_res ;
end;
//
delimiter ;
select my_translate_fx( '123123','23',' ');
-- select my_translate_fx( '123123','23','xy');
-- select my_translate_fx( '123123','1',' x');
-- select my_translate_fx( '123123','23','');
-- select my_translate_fx( '123123','','z');

Update row null fields with values from similar rows (same "key")

My question is kind of hard to explain in title so I'll show the data and goal.
There is a MySQL table with following structure:
CREATE TABLE customerProjectData(
idCustomer INT NOT NULL,
idProject INT DEFAULT NULL,
comePersons SMALLINT DEFAULT NULL,
comePairs SMALLINT DEFAULT NULL,
comment VARCHAR(255) DEFAULT NULL,
idCity INT DEFAULT NULL,
idStreet INT DEFAULT NULL,
name VARCHAR(64) DEFAULT NULL,
surname VARCHAR(64) DEFAULT NULL,
homeNum VARCHAR(10) DEFAULT NULL,
postCode CHAR(6) DEFAULT NULL,
postCity VARCHAR(64) DEFAULT NULL,
cellPhone VARCHAR(12) DEFAULT NULL
)
The thing is, there shold be also PRIMARY KEY(idCustomer, idProject) defined and it's not. As a result There are kind of duplicates (with the same primary key) but with different data.
I could run ALTER IGNORE TABLE but data loss would probably be unacceptable and unpredicatable. Finally we decided to try to fill null fields with values from duplicates if they contain data and after that run the ALTER IGNORE TABLE. Much less data will be lost that way and it's acceptable in this case (it's better than leaving it as it is now in longer time perspective).
The question is how to fill those fields from each duplicate.
Here is a rough try.
First try to find out the no. of rows which have the same key.
<?php
// $link is the database identifier
$sql = 'SELECT COUNT(*) AS num, * FROM `customerProjectData` GROUP BY `idCustomer`, `idProject` HAVING COUNT(*) > 1 ORDER BY COUNT(*) ASC;';
$run = mysql_query( $sql, $link );
$rows = array();
if( $run && mysql_num_rows( $run ) ) {
while( ( $fetch = mysql_fetch_assoc( $run ) ) !== false ) {
$rows[] = $fetch;
}
}
?>
Now $rows contains a list of all rows which have the same key and a count of how many times this key has been repeated in the table.
You can write a function which then iterates count times and see which rows has the complete data and use that to populates other records with this record's data.
A bit of trial and error.
I used #web-nomad suggestion and did something similar, but in sql procedure:
DROP PROCEDURE IF EXISTS correctCPD$$
CREATE PROCEDURE correctCPD()
BEGIN
DECLARE currentCustomerId INT;
DECLARE currentProjectId INT;
DECLARE cur_idCustomer INT;
DECLARE cur_idProject INT;
DECLARE cur_comePersons SMALLINT;
DECLARE cur_comePairs SMALLINT;
DECLARE cur_comment VARCHAR(255);
DECLARE cur_idCity INT;
DECLARE cur_idStreet INT;
DECLARE cur_name VARCHAR(64);
DECLARE cur_surname VARCHAR(64);
DECLARE cur_homeNum VARCHAR(10);
DECLARE cur_postCode CHAR(6);
DECLARE cur_postCity VARCHAR(64);
DECLARE cur_cellPhone VARCHAR(12);
CREATE TEMPORARY TABLE ids (
idCustomer INT,
idProject INT
) ENGINE = InnoDB;
INSERT INTO ids
SELECT idCustomer, idProject FROM customerprojectdata group by idCustomer, idProject having count(*) > 1;
BLOCK1: BEGIN
DECLARE done INT DEFAULT FALSE;
DECLARE itemCur CURSOR FOR SELECT idCustomer, idProject FROM ids;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
OPEN itemCur;
itemCurLoop: LOOP
FETCH itemCur INTO currentCustomerId, currentProjectId;
IF done THEN
LEAVE itemCurLoop;
END IF;
BLOCK2: BEGIN
DECLARE doneIn INT DEFAULT FALSE;
DECLARE cpdCur CURSOR FOR SELECT idCustomer, idProject, comePersons, comePairs, comment, idCity, idStreet, name, surname, homeNum, postCode, postCity, cellPhone FROM customerProjectData WHERE idCustomer = currentCustomerId AND idProject = currentProjectId;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET doneIn = TRUE;
OPEN cpdCur;
cpdCurLoop: LOOP
FETCH cpdCur INTO
cur_idCustomer, cur_idProject, cur_comePersons, cur_comePairs,
cur_comment, cur_idCity, cur_idStreet, cur_name, cur_surname,
cur_homeNum, cur_postCode, cur_postCity, cur_cellPhone;
IF doneIn THEN
LEAVE cpdCurLoop;
END IF;
UPDATE CustomerProjectData SET
comePersons = IF((comePersons IS NULL OR comePersons = '') AND cur_comePersons > 0, cur_comePersons, comePersons),
comePairs = IF((comePairs IS NULL OR comePairs = '') AND cur_comePairs > 0, cur_comePairs, comePairs),
comment = IF((comment IS NULL OR comment = '') AND cur_comment > 0, cur_comment, comment),
idCity = IF((idCity IS NULL AND idStreet IS NULL) AND cur_idCity > 0, cur_idCity, idCity),
idStreet = IF(((idCity IS NULL OR idCity = cur_idCity) AND idStreet IS NULL) AND cur_idStreet > 0, cur_idStreet, idStreet),
name = IF((name IS NULL OR name = '') AND cur_name > 0, cur_name, name),
surname = IF((surname IS NULL OR surname = '') AND cur_surname > 0, cur_surname, surname),
homeNum = IF((homeNum IS NULL OR homeNum = '') AND cur_homeNum > 0, cur_homeNum, homeNum),
postCode = IF((postCode IS NULL OR postCode = '') AND cur_postCode > 0, cur_postCode, postCode),
postCity = IF((postCity IS NULL OR postCity = '') AND cur_postCity > 0, cur_postCity, postCity),
cellPhone = IF((cellPhone IS NULL OR cellPhone = '') AND cur_cellPhone > 0, cur_cellPhone, cellPhone)
WHERE idCustomer = currentCustomerId AND idProject = currentProjectId;
END LOOP;
CLOSE cpdCur;
END BLOCK2;
END LOOP;
CLOSE itemCur;
END BLOCK1;
DROP TEMPORARY TABLE ids;
END$$
Thanks for help!

Convert a String to an array of characters or an alternative - Tsql

Getting this done in C# would have been such an easy task, but I am required to do this in sql. Basically, I need to write a tsql function that would convert a given varchar to it's corresponding encoding. For instance, if an input is '123456789' our business rule requires it be converted to 'ABCDEFGHI.' In short, I am trying to convert below c# code to tsql:
class Program
{
static void Main(string[] args)
{
string a = "1234567890";
char[] oldA = a.ToCharArray();
char[] newA = new char[10];
for (int i =0; i<oldA.Length; i++)
{
switch (oldA[i])
{
case '1':
newA[i] = 'A';
break;
case '2':
newA[i] = 'B';
break;
//and so on..
}
}
Console.WriteLine(newA);
Console.ReadKey();
}
}
I am confirmed that there is no array like thing in tsql, and most of the answers I came across assumed that it had some kind of delimiter to it, so wasn't particularly very useful.
Thanks.
You can do either
CREATE FUNCTION myfunc(#expr AS VARCHAR(255)) RETURNS VARCHAR(255)
BEGIN
RETURN REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(
REPLACE(#expr, '1', 'A'),
'2', 'B')
'3', 'C'),
'4', 'D'),
'5','E'),
'6', 'F'),
'7', 'G'),
'8', 'H'),
'9', 'I'),
'0','J')
END
or (which is much closer to what you've got in C#)
CREATE FUNCTION myfunc2(#expr AS VARCHAR(255)) RETURNS VARCHAR(255)
BEGIN
DECLARE #i AS INT = 1, #chr CHAR(1), #result VARCHAR(255) = ''
WHILE #i <= LEN(#expr)
BEGIN
SET #chr = SUBSTRING(#expr, #i, 1)
SET #result = #result +
CASE #chr
WHEN '1' THEN 'A'
WHEN '2' THEN 'B'
WHEN '3' THEN 'C'
WHEN '4' THEN 'D'
WHEN '5' THEN 'E'
WHEN '6' THEN 'F'
WHEN '7' THEN 'G'
WHEN '8' THEN 'H'
WHEN '9' THEN 'I'
WHEN '0' THEN 'J'
ELSE #chr
END
SET #i = #i + 1
END -- WHILE
RETURN #result
END
Sample usage for both functions:
SELECT dbo.myfunc(value) result, dbo.myfunc2(value) result2
FROM
(
VALUEs ('1234567890'), ('5512314567')
) t(value);
Sample output:
| RESULT | RESULT2 |
|------------|------------|
| ABCDEFGHIJ | ABCDEFGHIJ |
| EEABCADEFG | EEABCADEFG |
Here is a SQLFiddle demo
Here is a function that I put in most databases that I work with:
CREATE FUNCTION [dbo].[f_ForLoop](#Start INT , #End INT, #Increment INT = 1)
RETURNS #Loop TABLE
(
RowNumber INT
)
AS
--=============================================================
-- f_ForLoop
--
-- DATE AUTHOR DESCRIPTION
-- 17 Apr 2012 Nick McDermaid Created
--
-- PURPOSE:
-- Return a table that can be joined to with the number of records indicated in parameters
--
-- USAGE:
-- SELECT RowNumber FROM dbo.f_ForLoop(1,10,1)
-- SELECT RowNumber FROM dbo.f_ForLoop(10,1,-1)
-- SELECT RowNumber FROM dbo.f_ForLoop(2,20,2)
--=============================================================
BEGIN
IF #Increment = 0 RETURN
IF #Increment < 0 AND #Start < #End RETURN
IF #Increment > 0 AND #Start > #End RETURN
IF #Increment IS NULL SET #Increment = 1
WHILE NOT (#Start = #End)
BEGIN
INSERT INTO #Loop (RowNumber) VALUES (#Start)
SET #Start = #Start + #Increment
END
INSERT INTO #Loop (RowNumber) VALUES (#Start)
RETURN
END
Then you can use it something like this:
DECLARE #YourString VARCHAR(50)
SET #YourString='ABCDEFGHIJ'
SELECT
RowNumber,
SUBSTRING(#YourString,RowNumber,1) As Token,
ASCII(SUBSTRING(#YourString,RowNumber,1)) - 64 Result
FROM dbo.f_ForLoop(1,LEN(#YourString),1)
This is not exactly what you're after but serves to highlight some functionality.
The next step is to join to a mapping table instead of using ASCII because clearly this is not what you're after. This of course assume that one character is one token.
Based on peterm's second option (if it is safe to assume that all chars in the input will be between '0' and 9'):
CREATE FUNCTION myfunc2(#expr AS VARCHAR(255)) RETURNS VARCHAR(255)
BEGIN
DECLARE #i AS INT = 1, #chr CHAR(1), #result VARCHAR(255) = ''
WHILE #i <= LEN(#expr)
BEGIN
SET #chr = SUBSTRING(#expr, #i, 1)
SET #result = #result +
CASE #chr
WHEN '0' THEN 'J'
ELSE CHAR(64 + cast(#chr as int))
END
SET #i = #i + 1
END -- WHILE
RETURN #result
END
Or, possibly more efficient, since reduces the number of CAST calls:
CREATE FUNCTION myfunc2(#expr AS VARCHAR(255)) RETURNS VARCHAR(255)
BEGIN
DECLARE #i AS INT = 1, #b1 BINARY(1), #result VARCHAR(255) = ''
declare #b VARBINARY(255)
SET #b = CAST(#expr as VARBINARY(255))
WHILE #i <= LEN(#b)
BEGIN
SET #b1 = SUBSTRING(#b, #i, 1)
SET #result = #result +
CASE #b1
WHEN 48 THEN 'J' -- 48 is ascii '0'
ELSE CHAR(16 + #b1) -- to get from '1' to 'A' on ASCII chart, need to add 16.
END
SET #i = #i + 1
END -- WHILE
RETURN #result
END

Convert NULL Text to Null Value

I have a situation where I may need to pass a variable that could possibly hold a NULL value to a function, but through sp_executesql, so I will need to convert it to string value via string concatenation.
For Example:
declare #var1 varchar(10) = 'value'
declare #var2 varchar(10) = null
declare #sql nvarchar(2000)
.
.
set #sql = '
select dbo.fn_Scalar(''' + #var1 + ''', ''' + #var2 + ''' )
'
Function Definition:
Create Function [dbo].[fn_fn_Scalar]
(
#var1 varchar(10) ,
#var2 varchar(10) = null
) RETURNS float
AS BEGIN
Declare #ret float
Select #ret = sum(value)
from Table
where Field1 = #var1
and Field2 like isnull(#var2, '%')
return #ret
END
What would be the best approach to allow for fn_Scalar to be called via Dynamic and Static SQL statements and still allow for the second parameter to either be set to a value, NULL, or default.
You can pass parameters to sp_executesql function like so:
declare #var1 varchar(10) = 'value'
declare #var2 varchar(10) = null
Set #ParamDefinition = '#var1 varchar(10), #var2 varchar(10)'
Execute sp_Executesql 'select dbo.fn_Scalar(#var1,#var2)', #ParamDefinition, #var1, #var2

MySQL use ExtractValue(XML, 'Value/Values') to get all multiple values (split one column into rows)

I have a non-normal field containing multiple values because it is Xml data that wasn't intended to be queried, until now. Can MySQL split this xml column into multiple rows?
Table
NameA | <Xml><Values<Value>1</Value><Value>2</Value><Value>3</Value></Values></Xml>
NameB | <Xml><Values<Value>1</Value><Value>2</Value></Values></Xml>
NameC | <Xml><Values<Value>1</Value><Value>2</Value><Value>3</Value><Value>4</Value></Values></Xml>
I want
NameA | 1
NameA | 2
NameA | 3
NameB | 1
Like this MSSQL/TSQL solution
SELECT
I.Name,
Value.value('.','VARCHAR(30)') AS Value
FROM
Item AS I
CROSS APPLY
Xml.nodes('/Xml/Values/Value') AS T(Value)
WHERE
I.TypeID = 'A'
But in MySQL I can only get
NameA | 123
NameB | 12
NameC | 1234
with
SELECT
I.`Name`,
ExtractValue(Xml,'/Xml/Values/Value') AS ListOfValues
FROM
Item AS I
WHERE
I.TypeID = 'A'
;
Are there any elegant ways to split xml in MySQL?
No. You must solve this just like other mysql split column problems.
Can MySQL split a column?
Mysql string split
I.e. Specifically based on this answer
DROP FUNCTION IF EXISTS STRSPLIT;
DELIMITER $$
CREATE FUNCTION STRSPLIT($Str VARCHAR(20000), $delim VARCHAR(12), $pos INTEGER)
RETURNS VARCHAR(20000)
BEGIN
DECLARE output VARCHAR(20000);
SET output = REPLACE(SUBSTRING(SUBSTRING_INDEX($Str, $delim, $pos)
, LENGTH(SUBSTRING_INDEX($Str, $delim, $pos - 1)) + 1)
, $delim
, '');
IF output = ''
THEN SET output = null;
END IF;
RETURN output;
END $$
You can iterate through the values like so
DROP PROCEDURE IF EXISTS GetNameValues $$
CREATE PROCEDURE GetNameValues()
BEGIN
DECLARE i INTEGER;
DROP TEMPORARY TABLE IF EXISTS TempList;
CREATE TEMPORARY TABLE TempList(
`Name` VARCHAR(256) COLLATE utf8_unicode_ci NOT NULL,
`ValueList` VARCHAR(20000) COLLATE utf8_unicode_ci NOT NULL
);
DROP TEMPORARY TABLE IF EXISTS Result;
CREATE TEMPORARY TABLE Result(
`Name` VARCHAR(256) COLLATE utf8_unicode_ci NOT NULL,
`Value` VARCHAR(128) COLLATE utf8_unicode_ci NOT NULL
);
INSERT INTO
TempList
SELECT
I.`Name`,
ExtractValue(Xml,'/Xml/Values/Value') AS ValueList
FROM
Item AS I
WHERE
I.TypeID = 'A'
;
SET i = 1;
REPEAT
INSERT INTO
Result
SELECT
`Name`,
CAST(STRSPLIT(ValueList, ' ', i) AS CHAR(128)) AS Value
FROM
TempList
WHERE
CAST(STRSPLIT(ValueList, ' ', i) AS CHAR(128)) IS NOT NULL
;
SET i = i + 1;
UNTIL ROW_COUNT() = 0
END REPEAT;
SELECT * FROM Result ORDER BY `Name`;
END $$
DELIMITER ;
CALL GetNameValues();
Hope this helps someone one day.