разделение поля, разделенного запятыми, и использование в разделе «IN» оракула sql [duplicate]

2
задан NullUserException 24 September 2011 в 22:36
поделиться

5 ответов

Вы можете использовать LIKE. Вы не хотите соответствовать частичным значениям, поэтому вам придется включать запятые в свой поиск. Это также означает, что вам нужно будет предоставить дополнительную запятую для поиска значений в начале или конце текста:

select 
  * 
from
  YourTable 
where 
  ',' || CommaSeparatedValueColumn || ',' LIKE '%,SearchValue,%'

Но этот запрос будет медленным, как и все запросы с использованием LIKE, особенно с ведущим шаблоном.

И всегда есть риск. Если вокруг значений есть пробелы или значения могут содержать запятые, в этом случае они окружены кавычками (например, в файлах csv), этот запрос не будет работать, и вам придется добавить еще больше логики, замедляя ваш запрос еще больше.

Лучшим решением было бы добавить дочернюю таблицу для этих категорий. Или, скорее, даже отдельная таблица для каталогов и таблица, которая пересекает их с помощью YourTable.

10
ответ дан GolezTrol 25 August 2018 в 21:41
поделиться

Пока список с разделителями-запятыми составляет 512 символов или меньше, вы также можете использовать регулярное выражение в этом экземпляре (функции регулярного выражения Oracle, например REGEXP_LIKE(), ограничены 512 символами):

SELECT id, categories
  FROM mytable
 WHERE REGEXP_LIKE('c2', '^(' || REPLACE(categories, ',', '|') || ')$', 'i');

В вышеизложенном я заменяю запятые оператором чередования регулярных выражений |. Если ваш список ограниченных значений уже | -пределен, тем лучше.

1
ответ дан David Faber 25 August 2018 в 21:41
поделиться

Для будущих поисковиков не забудьте путь регулярного выражения:

with tbl as (
select 1 ID, 'c1' CATEGORIES from dual
union
select 2 ID, 'c2,c3' CATEGORIES from dual
union
select 3 ID, 'c3,c2' CATEGORIES from dual
union
select 4 ID, 'c3' CATEGORIES from dual
union
select 5 ID, 'c4,c8,c5,c100' CATEGORIES from dual
)
select * 
from tbl
where regexp_like(CATEGORIES, '(^|\W)c3(\W|$)');

        ID CATEGORIES
---------- -------------
         2 c2,c3
         3 c3,c2
         4 c3

Это соответствует границе слова, поэтому даже если запятая сопровождалась пробелом, оно все равно будет работать , Если вы хотите быть более строгим и соответствовать только там, где запятая разделяет значения, замените «\ W» запятой. Во всяком случае, прочитайте регулярное выражение как: соответствие группе либо начала строки, либо границы слова, за которой следует целевое значение поиска, за которым следует группа либо границы слова, либо конца строки.

1
ответ дан Gary_W 25 August 2018 в 21:41
поделиться

Вы можете написать функцию таблицы PIPELINED, которая возвращает 1 столбец столбца. Каждая строка представляет собой значение из строки, разделенной запятыми. Используйте это как pop строку из списка, а put - как строку в таблице:

PIPE ROW(ltrim(rtrim(substr(l_list, 1, l_idx - 1),' '),' '));

Использование:

SELECT * FROM MyTable 
WHERE 'c2' IN TABLE(Util_Pkg.split_string(categories));

Подробнее см. Здесь : Oracle docs

2
ответ дан MinhD 25 August 2018 в 21:41
поделиться

Да и Нет ...

«Да»:

Нормализовать данные (настоятельно рекомендуется) - т.е. разбить столбец категории, чтобы каждая категория была отдельной. .. тогда вы можете просто запросить его в обычном faschion ...

«Нет»: пока вы держите эту «псевдоструктуру», будет несколько проблем (производительность и другие), и вы будете должен сделать что-то похожее на:

SELECT * FROM MyTable WHERE categories LIKE 'c2,%' OR categories = 'c2' OR categories LIKE '%,c2,%' OR categories LIKE '%,c2'

ЕСЛИ вы абсолютно должны определить функцию, которая называется FIND_IN_SET, как показано ниже:

CREATE OR REPLACE Function FIND_IN_SET
   ( vSET IN varchar2, vToFind IN VARCHAR2 )
   RETURN number
IS
    rRESULT number;
BEGIN

rRESULT := -1;
SELECT COUNT(*) INTO rRESULT FROM DUAL WHERE vSET LIKE ( vToFine || ',%' ) OR vSET = vToFind OR vSET LIKE ('%,' || vToFind || ',%') OR vSET LIKE ('%,' || vToFind);

RETURN rRESULT;

END;

Затем вы можете использовать эту функцию например:

SELECT * FROM MyTable WHERE FIND_IN_SET (categories, 'c2' ) > 0;
1
ответ дан Yahia 25 August 2018 в 21:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: