3

如果我有一个名为 'Categories' 的列science,maths,english,并在行中以逗号分隔,如图所示,我将如何将所有行与包含的类别匹配maths

我尝试了一个简单LIKE但不太准确的方法,因为在搜索时'%science%'可能会匹配两者的“poo_science”。

我环顾了 StackOverflow,有很多类似的问题,但似乎都想以逗号分隔的列表或其他形式返回数据——这不是我想要的。

我宁愿不使用存储过程,也不能使用全文搜索。我有一个我使用的存储过程,它('$')在每个值周围添加了另一个字符,然后会搜索'$value$'...这是否太讨厌了?我追求更简单的方法。

4

6 回答 6

11

免责声明:评论员是对的……单个字段中的 CSV 是一个糟糕的设计,应该重新做。

话虽如此,以下是解决问题的方法:

Categories用前导和尾随填充,,这样您就可以将它们包含在通配符搜索中:

WHERE (',' + Categories + ',') LIKE '%,science,%'
于 2012-02-23T22:17:07.003 回答
7

使用 FIND_IN_SET(,)

SQL:

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

或者可以检查这个链接FIND_IN_SET() vs IN()

于 2013-06-07T04:11:13.820 回答
3

这个问题在google上是可见的并且有很多观点,所以我想分享我对这个问题的处理方法。我不得不处理如此糟糕的设计,因为逗号分隔的值也存储为字符串。我在调整负责标签的 CMS 插件时遇到了这个问题。

是的,与网站文章相关的标签是这样存储的:“ tag1,tag2,...,tagN ”。因此,获得精确匹配并不像最初出现的那么简单:使用 simple LIKE,文章标记为“ ball ”,我也得到了标记为“foot ball ”和“ ball room”的文章。不重要,但很烦人。

FIND_IN_SET函数起初看起来很棒,但后来发现它不使用索引并且如果第一个参数包含逗号字符则无法正常工作。

我不想改变插件本身或构建该插件的更深层次的 CMS 核心功能。

另外值得注意的是,需要的标记(子字符串)可以是字符串中的第一个、最后一个元素,也可以位于中间的某个位置,因此这段代码WHERE (',' + Categories + ',') LIKE '%,science,%'并未涵盖所有三种情况。

最后,我得到了非常简单的解决方案。它对我有用:

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

涵盖所有情况;逗号用作分隔符。希望它可以帮助遇到类似陷阱的其他人。

PS。我根本不是 MySQL/DB 专家,我很想了解这种方法的潜在缺点,尤其是在非常大的表上(这不是我的情况,顺便说一句)。我只是分享了我的小型研究的结果,以及我为解决这个问题所做的努力。

于 2017-03-05T18:58:54.160 回答
3

我提出了一个 4x WHERE 可以匹配任何可能的情况:单独的值、csv 开头、中间或结尾的值:

WHERE Categories = 'science'     /* CSV containing only the one value */
OR Categories LIKE 'science,%'   /* value at start of CSV */
OR Categories LIKE '%,science,%' /* value somewhere in the middle */
OR Categories LIKE '%,science'   /* value at the end of CSV */

这样,应该选择所有“科学”行,但不选择“poo_science”行。

于 2018-04-19T14:24:53.367 回答
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;

它绝对不会是超高效或非常可扩展的,但是处理非规范化数据往往会固有地存在这些问题。

于 2012-02-23T22:18:21.027 回答
1

使用 FIND_IN_SET() mysql 函数

句法

SELECT * FROM as a WHERE FIND_IN_SET(value to search in string,comma separated string);

例子

SELECT * FROM as a WHERE 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/

于 2016-12-27T13:50:53.270 回答