Dette kan gøres i sql . En måde ville være at bruge en "hjælpetabel" med kun heltal, som du kan join
dine data mod for at få din række flere gange og derefter for kun at udtrække n
-th underelement.
Prøv dette:
-- 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;
Dette vil give 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 | |
+---------------+----+-----------------+
Jeg brugte dine eksempeldata, der mangler nogle ,
, hvorfor resultatet indeholder bl.a. March 2 Feb 27
. Bemærk også, at nogle underposter er tomme (da mine eksempeldata inkluderer tomme poster); du vil måske ikke filtrere dem fra. Din heltalstabel skal naturligvis indeholde tal mindst op til det maksimale antal elementer, du forventer at have i nogen af dine rækker (og hvis den indeholder en 0
eller negative tal, filtrer dem fra i on
-klausul).
substring_index(str,delim,count)
returnerer understrengen fra strengen str
før count
forekomster af afgrænsningstegnet delim
. Den fulde erklæring for subentry
vil, for et positivt tal, returnere enten _int_1_10.id
-th element eller, hvis strengen har færre elementer, det sidste element.
on
-clausul beregner således antallet af elementer (ved at tælle antallet af ,
) for at undgå at få det sidste element flere gange. Hvis din streng ikke indeholder tomme elementer (såsom ,,
i mine eksempeldata), behøver du ikke den del, men du kan tilføje et tomt element for at markere slutningen af listen.
Du kan anvende denne kode på hele dit resultatsæt, f.eks. ved at bruge
...
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 vil virke, men det kan være langsomt. Den kan ikke bruge et indeks på space*_2_value
-kolonner og skal lave en masse sammenføjning og strengevaluering. Du kan dog ikke gøre meget ved det, bortset fra at normalisere dine data.
Hvis det er nyttigt at gøre dette i sql vil sandsynligvis afhænge af, hvad du laver med dataene. Hvis du bare skal vise det i en html-tabel på en webside, kan det være både nemmere og hurtigere blot at gå gennem arrayet i php . For at sortere, filtrere eller join
dit resultatsæt, er det sandsynligvis meget nemmere at implementere (og sandsynligvis hurtigere) i sql , måske endda hvis du bruger det i en ramme. Hvis du skal opdatere værdierne, vil det være meget nemmere at gøre i php , da det højst sandsynligt bliver noget rod i sql (på dette resultatsæt).