2012-02-23 3 views
1

Если у меня есть столбец с именем «Категории» с указанием science,maths,english в строке, разделенной запятой, как показано, как бы я совпадал со всеми строками с категорией, содержащей maths?Сопоставьте значения, разделенные запятой, в столбце

Я пробовал простой LIKE, но это не совсем точно, так как может быть «poo_science», который при поиске '%science%' соответствовал бы обоим.

Я просмотрел StackOverflow, и есть много похожих вопросов, но все, кажется, хотят вернуть данные в виде списка, разделенного запятой, или что-то еще - не совсем то, что мне нужно.

Я бы предпочел не использовать хранимую процедуру и не может использовать полнотекстовый поиск. У меня есть хранимая процедура, которую я использовал, которая добавила еще один символ ('$') вокруг каждого значения, а затем будет искать '$value$'..., это слишком противно? Я прошу немного более простой метод.

+9

Вот почему многозначные атрибуты являются ** злыми **. – Yuck

+0

@Yuck Я думал, что увеличение проблем с параллелизмом было то, почему они ** злые **. –

+5

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

ответ

9

Отказ от ответственности: комментаторы правы ... CSV в одном поле - ужасный дизайн, и его следует переделать.

С учетом сказанного, вот как вы можете работать вокруг проблемы:

Pad Categories с передней и задней ,, таким образом, вы можете включить их в подстановочные поиска:

WHERE (',' + Categories + ',') LIKE '%,science,%' 
+0

Я исправил крошечную ошибку синтаксиса. Это решение будет работать, и оно будет быстрее, чем решение XML. (Конечно, для этого потребуется сканирование таблицы или сканирование индекса). – usr

2

Я сделал некоторые предположения относительно вашего макета данных. Попробуйте это - с помощью SQL Server 2k8 + это должно работать:

DECLARE @SearchString NVarChar(100) = 'maths'; 

SELECT 1 SomeId, 'science,maths,english' Categories 
INTO #TestTable; 

WITH R AS (
    SELECT 
    X.SomeId, 
    C.value('@value', 'NVarChar(100)') SomeTagValue 
    FROM (SELECT SomeId, 
      CONVERT(XML, '<tag value = "' + REPLACE(Categories, ',', '" /><tag value = "') + '" />') XMLValue 
     FROM #TestTable) X CROSS APPLY X.XMLValue.nodes('//tag') T(C) 
) 
SELECT * 
FROM R 
WHERE SomeTagValue = @SearchString; 

DROP TABLE #TestTable; 

Это определенно не собирается быть супер-эффективными и очень масштабируемыми, но работает против денормализованных данных, как правило, по своей сути есть эти проблемы.

5

Использование FIND_IN_SET (,)

SQL:

SELECT name FROM orders,company 
WHERE orderID = 1 
AND 
FIND_IN_SET(companyID, attachedCompanyIDs) 

или может проверить эту ссылку FIND_IN_SET() vs IN()

+0

Whoa! Отличное решение для столбцов с разделителями-запятыми! Также заботится обо всех исключительных случаях. Должен был один из принятых ответов! – jahackbeth

+0

FIND_IN_SET - это только MySQL. Отличное решение, но не на SQL Server. – snort

1

использование FIND_IN_SET() функция MySQL

Синтаксис

SELECT * ОТ как ГДЕ FIND_IN_SET (значение для поиска в строке, строка, разделенная запятыми);

Пример

SELECT * FROM как ГДЕ FIND_IN_SET (5, "1,2,3,4,5,6");

Дополнительная информация Следуйте ссылке ниже:

http://blog.sqlauthority.com/2014/03/21/mysql-search-for-values-within-a-comma-separated-values-find_in_set/

1

Этот вопрос виден на Google и имеет много точек зрения, поэтому я хочу поделиться мой подход к этой проблеме. Мне приходилось иметь дело с таким плохим дизайном, как значения, разделенные запятыми, также сохраненные в виде строк. Я столкнулся с этой проблемой при настройке плагина CMS, ответственного за теги.

Да, теги, относящиеся к статье сайта, были сохранены следующим образом: «tag1, tag2, ..., TagN «Таким образом, получить точное совпадение не столь тривиально, как это могло бы иметь первоначально появился: с помощью простых LIKE с тегами статьи„мяча“Я также получил те помечен„ножной мяч “и» мяча номер». не критично, но скорее раздражает.

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

У меня не было желания изменять сам плагин или более глубокое ядро ​​CMS функциональность, на которой был построен этот плагин.

Также стоит отметить, что необходимый тег (подстрока) может быть первым, последним элементом в строке или может быть где-то посередине, поэтому этот фрагмент кода WHERE (',' + Categories + ',') LIKE '%,science,%' не охватывает все три случая.

Наконец-то я получил очень простое решение. Он работал для меня, как это:

... WHERE tags LIKE 'ball,%' OR tags LIKE '%,ball,%' OR tags LIKE '%,ball'

Все Theree случаев, охватываемых; запятые, используемые в качестве разделителей. Надеюсь, что это поможет другим, которые столкнулись с подобной ловушкой.

PS. Я вообще не эксперт по MySQL/DB, и мне бы хотелось прочитать о потенциальных недостатках этого подхода, особенно на действительно огромных таблицах (что не было моим делом, кстати). Я просто поделился результатами моих небольших исследований и тем, что я сделал, чтобы решить эту проблему с минимальными усилиями.

Смежные вопросы