【问题标题】:SP to find keywords like a list or stringsSP 查找关键字,如列表或字符串
【发布时间】:2010-11-06 08:10:01
【问题描述】:

在我的 mssql 数据库中,我有一个包含文章(id,名称,内容)的表,一个包含关键字(id,名称)的表以及文章和关键字之间的链接表 ArticleKeywords(articleId,keywordID,count)。计数是该关键字在文章中出现的次数。

如何编写一个 SP 来获取逗号分隔的字符串列表,并为我提供按文章中关键字出现次数排序的具有此关键字的文章? 如果一篇文章包含更多关键字,我想总结每个关键字的出现次数。

谢谢,拉杜

【问题讨论】:

  • 您好,您的问题对我来说很清楚,除了短语“...获取逗号分隔的字符串列表”。它是从哪里得到的?手写还是来自其他数据库或文本文件?

标签: sql sql-server stored-procedures


【解决方案1】:

虽然我并不完全清楚逗号分隔字符串的来源是什么,但我认为您想要的是一个将字符串作为输入并产生所需结果的 SP:

CREATE PROC KeywordArticleSearch(@KeywordString NVARCHAR(MAX)) AS BEGIN...

第一步是将逗号分隔的字符串垂直化为一个表格,其中的值以行为单位。这是在this questionanother question 中已广泛处理的问题,因此只需查看那里并选择其中一个选项。无论您选择哪种方式,都将结果存储在表变量或临时表中。

DECLARE @KeywordTable TABLE (Keyword NVARCHAR(128))
-- or alternatively...
CREATE TABLE #KeywordTable (Keyword NVARCHAR(128))

为了加快查找速度,最好存储 KeywordID,这样您的查询只需找到匹配的 ID:

DECLARE @KeywordIDTable TABLE (KeywordID INT)
INSERT INTO @KeywordTable 
    SELECT K.KeywordID FROM SplitFunctionResult S 
    -- INNER JOIN: keywords that are nonexistent are omitted
    INNER JOIN Keywords K ON S.Keyword = K.Keyword

接下来,您可以着手编写查询。这将是这样的:

SELECT articleId, SUM(count)
FROM ArticleKeywords AK
WHERE K.KeywordID IN (SELECT KeywordID FROM @KeywordIDTable)
GROUP BY articleID

或者您可以使用INNER JOIN 来代替WHERE。我认为查询计划不会有太大不同。

【讨论】:

  • 非常感谢。你拯救了我的一天:)
  • 一个关于 MSSQL 的快速问题:当我在 Name = '%' + name + '%' 上进行内部连接时,如何进行索引查找?
  • 呃。除非我忽略了某些东西,否则唯一的方法是将新字符串存储在临时表中:INSERT INTO #temp SELECT '%' + name + '%' AS derivedname 并在其上定义一个索引:CREATE INDEX index01 ON #temp (derivedname)。然后使用INNER JOIN #temp。但是你确定你不是说LIKE '%' + name + '%' 吗?优化这将是一个不同的故事......
  • 我的加入条件:Name LIKE '%' + name + '%'。我可以优化吗?奇怪的是我在执行计划中得到了一个索引搜索......但我认为它会进行表扫描。如何对 '%' + name + '%' 之类的东西进行索引搜索?
  • 我不知道,抱歉。但这将是一个很棒的新问题!之前好像也有人问过:stackoverflow.com/questions/1569002/…
【解决方案2】:

为了或争论,假设您要查找包含关键字 FooBarShazam 的所有文章。 p>

ALTER PROCEDURE spArticlesFromKeywordList

@KeyWords varchar(1000) = 'Foo,Bar,Shazam'
AS

SET NOCOUNT ON

DECLARE @KeyWordInClause varchar(1000)
SET @KeyWordInClause = REPLACE (@KeyWords ,',',''',''')

EXEC(
'
SELECT 
t1.Name as ArticleName,
t2.Name as KeyWordName,
t3.Count as [COUNT]
FROM ArticleKeywords t3
INNER JOIN Articles t1 on t3.ArticleId = t1.Id
INNER JOIN Keywords t2 on t3.KeywordId = t2.Id
WHERE t2.KeyWord in ( ''' + @KeyWordInClause  + ''') 
ORDER BY 
3 descending, 1
'
)

SET NOCOUNT OFF

【讨论】:

  • 这也不错。看到他有大约一百万篇文章,最好先将关键字转换为 id 并在 IN 子句中使用。
【解决方案3】:

我想我明白你在追求什么,所以在这里,(不确定你使用的是什么语言,但是)在 PHP 中(根据你的描述)我会使用 ORDER BY count DESC 语句查询 ArticleKeywords (即,最高优先) - 显然,您可以“通过关键字 ID 或文章 ID 进行选择。用非常简单的术语(因为这就是我 - 简单,可能有比我更好的人)您可以返回数组,但从中创建一个字符串,有点像这样:

$arraytostring .= $row->keywordID.',';

如果你离开加入表格,你可以创建这样的东西:

$arraytostring .= $row->keywordID.'-'.$row->name.' '.$row->content.',';

或者您可以将数组捕获为

$array[] = $row->keywordID;

并在循环外创建您的字符串。

注意:您有 2 个名为“名称”的字段,一个在文章中,一个在关键字中,重命名其中一个会更容易以避免任何冲突(假设它们不是相同的内容),即文章名称 = 标题和关键字名称=关键字

【讨论】:

  • 我想做的是一个存储过程……因为有将近一百万篇文章……我无法全部加载。我有人可以给我 sp 如何解析 csv 关键字并将它们的 id 添加到临时表的开始就足够了
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多