Поиск столбца, содержащего данные CSV в таблице MySQL на наличие входных значений - PullRequest
4 голосов
/ 18 мая 2010

У меня есть таблица, скажем, ITEM, в MySQL, которая хранит данные следующим образом:

ID    FEATURES
--------------------
1     AB,CD,EF,XY
2     PQ,AC,A3,B3
3     AB,CDE
4     AB1,BC3
--------------------

В качестве ввода я получу строку CSV, что-то вроде "AB, PQ". Я хочу получить записи, которые содержат AB или PQ. Я понял, что мы должны написать функцию MySQL для достижения этой цели. Итак, если у нас есть эта магическая функция MATCH_ANY, определенная в MySQL, которая делает это, я бы просто выполнил SQL следующим образом:

select * from ITEM where MATCH_ANY(FEAURES, "AB,PQ") = 0

Приведенный выше запрос вернет записи 1, 2 и 3.

Но при реализации этой функции я сталкиваюсь с множеством проблем, поскольку понял, что MySQL не поддерживает массивы и нет простого способа разбить строки на основе разделителя.

Модернизация таблицы - это последний вариант для меня, поскольку она связана с множеством проблем.

Возможно, я также захочу выполнить запросы, содержащие несколько функций MATCH_ANY, таких как:

select * from ITEM where MATCH_ANY(FEATURES, "AB,PQ") = 0 and MATCH_ANY(FEATURES, "CDE")

В приведенном выше случае мы получили бы пересечение записей (1, 2, 3) и (3), которое было бы всего 3.

Любая помощь очень ценится.

Спасибо

Ответы [ 5 ]

7 голосов
/ 18 мая 2010

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

select distinct i.Itemid
from Item i
inner join ItemFeature f on f.ItemId = i.ItemId
where f.Feature in ('AB', 'PQ')

Вы можете сопоставлять строки в значениях через запятую, но это не очень эффективно:

select Id
from Item
where
  instr(concat(',', Features, ','), ',AB,') <> 0 or
  instr(concat(',', Features, ','), ',PQ,') <> 0
3 голосов
/ 09 ноября 2015

Для всех вас, любителей REGEXP, я подумал, что добавлю это в качестве решения:

SELECT * FROM ITEM WHERE FEATURES REGEXP '[[:<:]]AB|PQ[[:>:]]';

и для чувствительности к регистру:

SELECT * FROM ITEM WHERE FEATURES REGEXP BINARY '[[:<:]]AB|PQ[[:>:]]';

Для второго запроса:

SELECT * FROM ITEM WHERE FEATURES REGEXP '[[:<:]]AB|PQ[[:>:]]' AND FEATURES REGEXP '[[:<:]]CDE[[:>:]];

Ура!

3 голосов
/ 18 мая 2010
select * 
  from ITEM where 
 where CONCAT(',',FEAURES,',') LIKE '%,AB,%'
    or CONCAT(',',FEAURES,',') LIKE '%,PQ,%'

или создайте пользовательскую функцию для выполнения вашего MATCH_ANY

1 голос
/ 18 мая 2010

В качестве альтернативы рассмотрите возможность использования RLIKE ()

    select * 
      from ITEM
     where ','+FEATURES+',' RLIKE ',AB,|,PQ,'; 
0 голосов
/ 18 мая 2010

Просто мысль:

Должно ли это быть сделано в SQL? Это та вещь, которую вы обычно можете написать на PHP, Python или на любом другом языке, который вы используете для взаимодействия с базой данных.

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

Ben

...