Привет всем. Прошу помочь. в БД имеются записи диапазонов. цель "нормализировать" их , записать по возрастанию. вот пример записи исходные данные
2018-2021, 2015-2015, 2014-2021, 2017-2021, 2015-, 2017-2018, 2018-, 2015-2021, 2015-2018, 2014-2015, 2014-2014, 2016-, 2017-, 2014-2017, 2019-, 2016-2021, 2018-2018, 2014-2016, 2017-2019, 2015-2016, 2015-2021, 2014-2015, 2013-2014, 2016-2021, 2020-, 2013-2016, 2015-2018, 2012-, 2012-2012, 2013-, 2014-2016, 2011-2014, 2015-2016, 2010-2012, 2016-, 2019-, 2012-2021, 2012-2015, 2010-2013, 2012-2014, 2012-2016, 2010-2011, 2011-2013, 2011-2012, 2010-2010, 2011-2008, 2012-2018, 2014-2021, 2018-2020, 2018-, 2015-2015, 2015-2017, 2014-2014, 2015-2019, 2010-2008, 2013-2015, 2013-2021, 2015-, 2012-2013, 2011-2016, 2010-2016, 2013-2018
с ней нужно сделать вот так
2008/2009/2010/2011/2012/2013/2014/2015/2016/2017/2018/2019/2020/2021
Пробовали делать вот так
-- Удаляем временную таблицу, если она уже существует
DROP TABLE IF EXISTS temp_final_result;
-- Создаём временную таблицу для обработки
CREATE TEMPORARY TABLE temp_final_result AS
WITH RECURSIVE
-- Разбиваем текст на отдельные диапазоны
split_ranges AS (
SELECT
product_id,
attribute_id,
-- Удаляем пробелы и разделяем диапазоны по запятым
TRIM(SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(text, ' ', ''), ',', n.n), ',', -1)) AS range_part
FROM
oc_product_attribute_copy1
JOIN (
SELECT 1 AS n
UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4
UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10
UNION ALL SELECT 11 UNION ALL SELECT 12 UNION ALL SELECT 13
) n
ON CHAR_LENGTH(text) - CHAR_LENGTH(REPLACE(text, ',', '')) + 1 >= n.n
WHERE attribute_id = 1033 -- Условие для фильтрации записей
),
-- Парсим диапазоны (учитываем прямые и обратные)
parsed_ranges AS (
SELECT
product_id,
attribute_id,
CASE
WHEN range_part LIKE '%-%' THEN CAST(SUBSTRING_INDEX(range_part, '-', 1) AS UNSIGNED)
ELSE NULL
END AS raw_Xmin,
CASE
WHEN range_part LIKE '%-%' THEN
CASE
WHEN SUBSTRING_INDEX(range_part, '-', -1) = '' THEN NULL -- Открытые диапазоны
ELSE CAST(SUBSTRING_INDEX(range_part, '-', -1) AS UNSIGNED)
END
ELSE NULL
END AS raw_Xmax
FROM split_ranges
),
-- Учитываем обратные диапазоны
adjusted_ranges AS (
SELECT
product_id,
attribute_id,
LEAST(raw_Xmin, raw_Xmax) AS Xmin, -- Минимальное значение
GREATEST(raw_Xmin, raw_Xmax) AS Xmax -- Максимальное значение
FROM parsed_ranges
),
-- Генерируем все годы в диапазоне
generated_years AS (
SELECT
product_id,
attribute_id,
Xmin + n AS year
FROM adjusted_ranges
JOIN (
SELECT 0 AS n UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15
UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19
UNION ALL SELECT 20 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23
UNION ALL SELECT 24 UNION ALL SELECT 25 UNION ALL SELECT 26 UNION ALL SELECT 27
) numbers
ON n <= (Xmax - Xmin)
WHERE Xmin IS NOT NULL AND Xmax IS NOT NULL -- Игнорируем некорректные диапазоны
),
-- Убираем дубликаты и формируем строку
final_text AS (
SELECT
product_id,
attribute_id,
GROUP_CONCAT(DISTINCT year ORDER BY year ASC SEPARATOR '/') AS new_text
FROM generated_years
GROUP BY product_id, attribute_id
)
-- Сохраняем результат в временной таблице
SELECT * FROM final_text;
UPDATE oc_product_attribute_copy1 o
JOIN temp_final_result r
ON o.product_id = r.product_id AND o.attribute_id = r.attribute_id
SET o.text = r.new_text
WHERE o.attribute_id = 1033;
Получаем вот такой результат
2014/2015/2016/2017/2018/2019/2020/2021
в итоге не все диапазоны обрабатывает что есть в исходных данных. не обрабатывает обратные диапазоны типа таких 2010-2008 2011-2008
пример таблицы с исходными данными.
Отредактированно Petr (21.11.2024 16:56:46)
Прикрепленные файлы:
oc_product_attribute_copy1.sql, Размер: 4,967 байт, Скачано: 14