Detta kan göras i sql . Ett sätt skulle vara att använda en "hjälpartabell" med bara heltal som du kan join
dina data mot för att hämta din rad flera gånger och sedan extrahera bara n
-th subelement.
Prova detta:
-- helper table with a listof integers from 1 to 10
create table _int_1_10 (id int primary key);
insert into _int_1_10 (id)
values (1), (2), (3), (4), (5), (6), (7), (8), (9), (10);
-- some example data
create table test_strexplode (
id int primary key,
space_value_1 varchar(200),
space_value_2 varchar(200)
);
insert into test_strexplode (id, space_value_1, space_value_2)
values (1, 'row 1', 'March 3,March 5,March 6 March 1,March 2 Feb 27'),
(2, 'row 2', 'March 3,,March 5'),
(3, 'row 3', '');
select space_value_1,
_int_1_10.id,
-- extracts the "_int_1_10.id"th element
SUBSTRING_INDEX(SUBSTRING_INDEX(
space_value_2,',',_int_1_10.id),',',-1) as subentry
from test_strexplode
join _int_1_10
on _int_1_10.id <=
-- number of elements in your string (= number of "," + 1)
char_length(space_value_2) - char_length(replace(space_value_2, ',', '')) + 1
order by test_strexplode.id, _int_1_10.id;
Detta ger dig:
+---------------+----+-----------------+
| space_value_1 | id | subentry |
+---------------+----+-----------------+
| row 1 | 1 | March 3 |
| row 1 | 2 | March 5 |
| row 1 | 3 | March 6 March 1 |
| row 1 | 4 | March 2 Feb 27 |
| row 2 | 1 | March 3 |
| row 2 | 2 | |
| row 2 | 3 | March 5 |
| row 3 | 1 | |
+---------------+----+-----------------+
Jag använde dina exempeldata som saknar ,
, varför resultatet innehåller t.ex. March 2 Feb 27
. Observera också att vissa underposter är tomma (eftersom mina exempeldata inkluderar tomma poster); du kanske vill eller kanske inte vill filtrera bort dem. Din heltalstabell måste uppenbarligen innehålla nummer åtminstone upp till det maximala antalet element du förväntar dig att ha i någon av dina rader (och om den innehåller en 0
eller negativa tal, filtrera bort dem i on
-klausul).
substring_index(str,delim,count)
returnerar delsträngen från strängen str
före count
förekomster av avgränsaren delim
. Det fullständiga uttalandet för subentry
kommer, för ett positivt tal, att returnera antingen _int_1_10.id
-th element eller, om strängen har färre element, det sista elementet.
on
-clausul beräknar alltså antalet element (genom att räkna antalet ,
) för att förhindra att det sista elementet hämtas flera gånger. Om din sträng inte innehåller några tomma element (som ,,
i mina exempeldata) behöver du inte den delen men kan lägga till ett tomt element för att markera slutet på listan.
Du kan tillämpa denna kod på hela din resultatuppsättning, t.ex. genom att använda
...
from (select ...
space1_1_value as space_value_1,
space1_2_value as space_value_2
...
union all ... union all ... ) as test_strexplode
join _int_1_10 ...
Det kommer att fungera, men det kan vara långsamt. Den kan inte använda ett index på space*_2_value
-kolumner och kommer att behöva göra mycket sammanfogning och sträng-utvärdering. Du kan dock inte göra mycket åt det, förutom att normalisera dina data.
Om det är användbart att göra detta i sql kommer förmodligen att bero på vad du gör med datan. Om du bara ska visa den i en html-tabell på en webbsida kan det vara både enklare och snabbare att bara gå igenom arrayen i php . För att sortera, filtrera eller join
din resultatuppsättning är det förmodligen mycket lättare att implementera (och förmodligen snabbare) i sql , kanske även om du använder det i ett ramverk. Om du ska uppdatera värdena blir det mycket lättare att göra i php , eftersom det med största sannolikhet kommer att bli en enda röra i sql (på denna resultatuppsättning).