Вот один (раздутый / грязный) подход к получению нужного набора данных ...
Шаг 1 - выяснить, каково максимальное количество идентификаторов выдачи
SELECT MAX(LENGTH(comments)- LENGTH(REPLACE(comments,'#',''))) AS max_issues
FROM change_sets
Шаг 2 - рекурсивно создайте запрос UNION с числом «уровней», равным максимальному количеству идентификаторов выдачи. Для вашего примера
SELECT changeset_id, issue_id FROM
(
SELECT id AS changeset_id, CAST(SUBSTRING_INDEX(comments,'#',-1) AS UNSIGNED) AS issue_id FROM change_sets
UNION
SELECT id AS changeset_id, CAST(SUBSTRING_INDEX(comments,'#',-2) AS UNSIGNED) AS issue_id FROM change_sets
UNION
SELECT id AS changeset_id, CAST(SUBSTRING_INDEX(comments,'#',-3) AS UNSIGNED) AS issue_id FROM change_sets
) a
HAVING issue_id!=0
ORDER BY changeset_id, issue_id
Я принимаю во внимание способность UNION удалять дублирующиеся строки и способность CAST использовать начальные числовые значения при определении целого числа.
Результат с использованием вашего игрушечного набора данных:
+--------------+----------+
| changeset_id | issue_id |
+--------------+----------+
| 1 | 234 |
| 2 | 123 |
| 2 | 789 |
| 2 | 7895 |
| 3 | 129 |
+--------------+----------+