SQLinfo.ru - Все о MySQL

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 21.11.2024 16:55:30

Petr
Завсегдатай
Откуда: Москва
Зарегистрирован: 19.10.2011
Сообщений: 51

Проверка диапазонов

Привет всем. Прошу помочь. в БД имеются записи диапазонов. цель "нормализировать" их , записать по возрастанию. вот пример записи исходные данные

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)


Прикрепленные файлы:
Attachment Icon oc_product_attribute_copy1.sql, Размер: 4,967 байт, Скачано: 14

Работаю над Сайтом http://tuningdom.ru/, Ищу гуру которого можно спросить обо Всем!

Неактивен

 

#2 21.11.2024 21:53:58

Petr
Завсегдатай
Откуда: Москва
Зарегистрирован: 19.10.2011
Сообщений: 51

Re: Проверка диапазонов

всем спасибо. разобрался сам.


Работаю над Сайтом http://tuningdom.ru/, Ищу гуру которого можно спросить обо Всем!

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson