使用 SQL 查询在数据为 "a,z,b,c,x" 的列中查找 "a,b,c"

Look for "a,b,c" in column with data "a,z,b,c,x" with SQL query

我一直在重构和升级一个现有新闻站点的数据层,这不是我从一开始就开发的。该应用程序进行了大量访问,经过一些研究后,我决定放弃 EF 并使用 Ado.Net / Dapper,因为 sql 命令永远不会暴露于任何类型的 UI 图层或字符串操作。

我遇到的一个问题是,很难,新闻标签在数据库中没有规范化,并且在新闻中存储为逗号分隔的字符串 table 并且有一个前端功能需要 "related news" 显示给用户。

所以我需要在还包含逗号分隔字符串值的 table 列中搜索 任何 次逗号分隔字符串值。

我在 sql management studio 中提出了以下查询,但(显然)需要很长时间才能 return 结果。有没有办法更好地进行此操作?我没有 SQL 方面的专业知识,所以据我所知,这是目前有效的查询:

-- I'm declaring this variable only for testing. In reality, @Tags should also be a query
-- which returns the set of tags of the target news...
DECLARE @Tags nvarchar(MAX)
Select @Tags = Tags FROM News WHERE Id = 7978 -- No idea where / how to include this query
-- in the actual search query :/

-- dbo.Split is a table valued function that takes a comma delimited nvarchar as parameter
-- and returns table(Id int, Data nvarchar, Order int) with the seperated values of the CSV
SELECT DISTINCT TOP 10 N.Id, N.Title, N.CreatedAt From News N
CROSS APPLY dbo.Split(N.Tags) B
WHERE B.Data IN
(
    SELECT C.Data FROM dbo.Split(@Tags) C
)
ORDER BY N.CreatedAt DESC, N.Id DESC

我为新闻 table 中的 "Tags" 列启用并设置了全文索引,但想不出一个合适的查询来利用它的好处。

SQL服务器版本:2008 R2

此查询应该提供 IEnumerable<NewsDto> GetRelatedNews(int targetNewsId) api 方法。

你会尝试以下查询吗:

SELECT DISTINCT TOP 10 n.Id, n.Title, n.CreatedAt
FROM dbo.Split(@Tags) c
CROSS APPLY
(
    SELECT id, Title, CreatedAt
    FROM News 
    WHERE CONTAINS(Tags, c.Data) //THIS SHOULD MAKE USE OF FT
) n

但一个缺点是它可能会从第一个标签中获取所有前 10 条新闻。

进一步的研究并没有产生任何替代方案来替代我在原始 post 中作为示例给出的方案。所以我决定使用该查询并将其转换为存储过程。

return 所有结果需要 3 秒,在我的 Web 项目中,我通过 ajax 调用此方法并缓存结果以防止 运行 每个相同的 SP请求。

总体而言,它不会影响我的 WebUI 性能,因为它异步加载相关新闻并使用缓存结果(如果存在)。