Można to zrobić w sql . Jednym ze sposobów byłoby użycie „tabeli pomocniczej” zawierającej tylko liczby całkowite, do których możesz join
swoje dane, aby uzyskać wiersz kilka razy, a następnie wyodrębnić tylko n
-ty podelement.
Spróbuj tego:
-- 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;
To da ci:
+---------------+----+-----------------+
| 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 | |
+---------------+----+-----------------+
Użyłem Twoich przykładowych danych, w których brakuje niektórych ,
, dlatego wynik zawiera m.in. March 2 Feb 27
. Zauważ też, że niektóre wpisy podrzędne są puste (ponieważ moje przykładowe dane zawierają puste wpisy); możesz lub nie chcesz ich odfiltrować. Twoja tabela liczb całkowitych będzie oczywiście musiała zawierać liczby co najmniej do maksymalnej liczby elementów, których oczekujesz w dowolnym wierszu (i jeśli zawiera 0
lub liczb ujemnych, odfiltruj je w on
-klauzula).
substring_index(str,delim,count)
zwraca podciąg z ciągu str
przed count
wystąpienia ogranicznika delim
. Pełna instrukcja dla subentry
w przypadku liczby dodatniej zwróci _int_1_10.id
-ty element lub, jeśli ciąg ma mniej elementów, ostatni element.
on
-klauzula w ten sposób oblicza liczbę elementów (licząc liczbę ,
), aby zapobiec kilkukrotnemu pobieraniu ostatniego elementu. Jeśli Twój ciąg nie zawiera żadnych pustych elementów (takich jak ,,
w moich przykładowych danych), nie potrzebujesz tej części, ale możesz dodać pusty element, aby zaznaczyć koniec listy.
Możesz zastosować ten kod do całego zestawu wyników, np. za pomocą
...
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 ...
To zadziała, ale może być powolne. Nie może używać indeksu w space*_2_value
-kolumny i będzie musiał wykonać dużo łączenia i oceny ciągów. Nie możesz jednak wiele z tym zrobić, z wyjątkiem normalizacji danych.
Jeśli warto to zrobić w sql prawdopodobnie będzie zależeć od tego, co robisz z danymi. Jeśli zamierzasz wyświetlić go tylko w tabeli html na stronie internetowej, może być zarówno łatwiej, jak i szybciej po prostu przejść przez tablicę w php . Sortowanie, filtrowanie lub join
Twój zestaw wyników, prawdopodobnie łatwiej jest go zaimplementować (i prawdopodobnie szybciej) w sql , może nawet jeśli używasz go w frameworku. Jeśli zamierzasz zaktualizować wartości, będzie to znacznie łatwiejsze w php , ponieważ najprawdopodobniej będzie bałagan w sql (w tym zestawie wyników).