SQLinfo.ru - Все о MySQL

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

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

Вы не зашли.

#1 31.03.2010 23:36:04

Byakuya
Участник
Зарегистрирован: 31.03.2010
Сообщений: 1

Сложная выборка по подстроке с регулярными выражениями

Добрый день.
Необходимо реализовать ряд запросов следующего типа: есть таблица с полем типа text, в нём хранится текст примерно следующего плана:
[{"id":"1","value":"1"},{"id":"2","value":"2"},{"id":"3","value":"22"},{"id":"4","value":"222"},{"id":"5","value":"7"}]
Т.е. порядковый номер (id) и некоторое значение.
Надо сделать запросы по простому вхождению подстроки, тут всё просто - используем like '%%'.
Второй тип запросов более сложный: туда передаётся максимальное и минимальное число (в некоторых случаях только максимальное или только минимальное) и надо найти для определенных id (допустим id = 3 и id = 4) значения (value), которые входят в переданный диапазон.
Вроде как есть регулярные выражения в mysql, стоит ли с ними работать или они сильно тормозные?
В БД будет максимум 200-250 строк с такими полями.

Неактивен

 

#2 01.04.2010 00:47:58

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Сложная выборка по подстроке с регулярными выражениями

Вообще я бы на вашем месте денормализовал немножко таблицу и хранил значения id и value в отдельных столбцах.

Регулярные выражения здесь не помогут, т.к. в MySQL они не умеют захватывать части строк, а позволяют лишь проверить, соответствует ли строка заданному выражению.
Однако решение существует. Оно довольно громоздкое и весьма ресурсоемкое: запрос не будет использовать индексы вообще, т.е. понадобится полный скан таблицы; кроме того, при его выполнении понадобится создание временной таблицы. Впрочем, при ваших объемах это не страшно, так что приступим.

Для начала рассмотрим задачу, как из строки вида '{"id":"N","value":"M"}' получить N и M. Один из возможных путей - через функцию SUBSTRING_INDEX().
(он не очень гибкий, но в данном случае один из наиболее простых и быстрых).
Здесь используем такое свойство формата ваших записей, каждая запись содержит 8 кавычек, причем N - между 3-ой и 4-ой, а M - между 6-ой и 7-ой.
SUBSTRING_INDEX( '{"id":"N","value":"M"}', '"', 4 ) даст строку '{"id":"N'. Соответственно, нужно еще раз применить SUBSTRING_INDEX(), чтобы получить часть [уже новой] строки справа от последней кавычки: для этого нужно в качестве третьего аргумента передать -1 (т.е. "справа от первой кавычки с конца").
Поэтому число N (т.е. значение id) даст вот такое выражение:

SELECT
    SUBSTRING_INDEX(
        SUBSTRING_INDEX('{"id":"N","value":"M"}', '"', 4),
        '"',
        -1    )


Соответственно, для M нужно 8 вместо 4.

В общем, требуемый запрос будет примерно таким:

SELECT *
FROM table
WHERE
    SUBSTRING_INDEX( SUBSTRING_INDEX(text, '"', 4), '"', -1 ) IN (список id)
    AND    
    SUBSTRING_INDEX( SUBSTRING_INDEX(text, '"', 8), '"', -1 ) BETWEEN min AND max
 


Если нужно для id1 min1 и max1, для id2 - min2 и max2, то придется конструировать соответствующие условия и объединять через OR:

SELECT *
FROM table
WHERE
    (
        SUBSTRING_INDEX( SUBSTRING_INDEX(text, '"', 4), '"', -1 ) = id1
        AND
        SUBSTRING_INDEX( SUBSTRING_INDEX(text, '"', 8), '"', -1 ) BETWEEN min1 AND max1
    )
    OR
    (
        SUBSTRING_INDEX( SUBSTRING_INDEX(text, '"', 4), '"', -1 ) = id2
        AND
        SUBSTRING_INDEX( SUBSTRING_INDEX(text, '"', 8), '"', -1 ) BETWEEN min2 AND max2
    )
    OR
    ...
 

Неактивен

 

Board footer

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