Điều này có thể được thực hiện trong sql . Một cách là sử dụng "bảng trợ giúp" chỉ với các số nguyên mà bạn có thể join
dữ liệu của bạn chống lại để lấy hàng của bạn nhiều lần và sau đó chỉ trích xuất n
-thành phần phụ.
Hãy thử điều này:
-- 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;
Điều này sẽ cung cấp cho bạn:
+---------------+----+-----------------+
| 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 | |
+---------------+----+-----------------+
Tôi đã sử dụng dữ liệu mẫu của bạn bị thiếu một số ,
, đó là lý do tại sao kết quả chứa ví dụ:March 2 Feb 27
. Cũng lưu ý rằng một số truy vấn con trống (vì dữ liệu mẫu của tôi bao gồm các mục nhập trống); bạn có thể muốn hoặc không muốn lọc chúng ra. Bảng số nguyên của bạn rõ ràng sẽ phải chứa số ít nhất lên đến số phần tử tối đa mà bạn mong đợi có trong bất kỳ hàng nào của mình (và nếu nó chứa 0
hoặc số âm, hãy lọc chúng ra trong on
-nhưng).
substring_index(str,delim,count)
trả về chuỗi con từ chuỗi str
trước count
sự xuất hiện của dấu phân tách delim
. Tuyên bố đầy đủ cho subentry
đối với một số dương sẽ trả về _int_1_10.id
-thành phần hoặc, nếu chuỗi có ít phần tử hơn, phần tử cuối cùng.
on
-clause tính toán số lượng phần tử (bằng cách đếm số lượng của ,
) để ngăn việc nhận phần tử cuối cùng nhiều lần. Nếu chuỗi của bạn không chứa bất kỳ phần tử trống nào (như ,,
trong dữ liệu mẫu của tôi), bạn không cần phần đó nhưng có thể thêm một phần tử trống để đánh dấu phần cuối của danh sách.
Bạn có thể áp dụng mã này cho toàn bộ tập kết quả của mình, ví dụ:bằng cách sử dụng
...
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 ...
Nó sẽ hoạt động, nhưng nó có thể chậm. Nó không thể sử dụng chỉ mục trên space*_2_value
-các cột và sẽ phải thực hiện nhiều phép nối và đánh giá chuỗi. Tuy nhiên, bạn không thể làm gì nhiều về nó, ngoại trừ việc chuẩn hóa dữ liệu của bạn.
Nếu việc này hữu ích trong sql có thể sẽ phụ thuộc vào những gì bạn đang làm với dữ liệu. Nếu bạn chỉ định hiển thị nó trong một bảng html trên một trang web, thì việc lặp qua mảng trong php có thể dễ dàng hơn và nhanh hơn . Để sắp xếp, lọc hoặc join
tập kết quả của bạn, nó có thể dễ triển khai hơn nhiều (và có thể nhanh hơn) trong sql , có thể ngay cả khi bạn đang sử dụng nó trong một khuôn khổ. Nếu bạn định cập nhật các giá trị, thì việc thực hiện trong php sẽ dễ dàng hơn nhiều , vì rất có thể sẽ là một mớ hỗn độn trong sql (trên tập kết quả này).