选择基于从单个表的关键字相关的文章(SELECT related articles based on

2019-10-17 14:43发布

我工作的一个Web项目,显示了它的一个网页文章的细节和侧面我还需要证明基于前5名相关文章keywordstags

我我怎么可以完全不使用T-SQL,而不是从代码做处理的一部分,它背后我不知道。

我使用功能分裂我的关键字,并通过结果等查询来获取这不是为我工作所需的结果。

CREATE TABLE Article
(
 ArticleID int,
 Title varchar(200),
 Description varchar(500),
 Details nvarchar(MAX),
 keywords varchar(100)
 )

INSERT INTO Article VALUES(1, 'Article One','Article desc', 'article details', 'one,two,three')
INSERT INTO Article VALUES(2, 'Article Two','Article desc', 'article details', 'two,three,four')
INSERT INTO Article VALUES(3, 'Article three','Article desc', 'article details', 'three,four,five')
INSERT INTO Article VALUES(4, 'Article four','Article desc', 'article details', ',four,five,six')
INSERT INTO Article VALUES(5, 'Article five','Article desc', 'article details', 'two,three')
INSERT INTO Article VALUES(6, 'Article six','Article desc', 'article details', 'eight, nine')
INSERT INTO Article VALUES(7, 'Article six','Article desc', 'article details', 'ten, nine')
INSERT INTO Article VALUES(8, 'Article six','Article desc', 'article details', 'eleven, eight')

功能

CREATE FUNCTION [dbo].[uf_SplitKeywords] 
   (  @DELIMITER VARCHAR(5), 
      @LIST      VARCHAR(MAX) 
   ) 
   RETURNS @TABLEOFVALUES TABLE 
      (  ROWID   SMALLINT IDENTITY(1,1), 
         [VALUE] VARCHAR(MAX) 
      ) 
AS 
   BEGIN

      DECLARE @LENSTRING INT 

      WHILE LEN( @LIST ) > 0 
         BEGIN 

            SELECT @LENSTRING = 
               (CASE CHARINDEX( @DELIMITER, @LIST ) 
                   WHEN 0 THEN LEN( @LIST ) 
                   ELSE ( CHARINDEX( @DELIMITER, @LIST ) -1 )
                END
               ) 

            INSERT INTO @TABLEOFVALUES 
               SELECT SUBSTRING( @LIST, 1, @LENSTRING )

            SELECT @LIST = 
               (CASE ( LEN( @LIST ) - @LENSTRING ) 
                   WHEN 0 THEN '' 
                   ELSE RIGHT( @LIST, LEN( @LIST ) - @LENSTRING - 1 ) 
                END
               ) 
         END

      RETURN 

   END

我需要的?

显示ID为3条

SELECT ArticleID, Title, Keywords FROM Article WHERE ArticleID = 3

然后,我需要展示基于关键字的相关文章three,four,five从选择的物品,在这种情况下应该是文章与articleid=3在这种情况下,结果应该显示我的id 1,2,3,4,5为关键字的文章配合仅这些行。

我想这是不工作与下面的查询来实现这一目标

SELECT TOP 5 ArticleID, Title, Keywords FROM Articles WHERE Keywords IN
(SELECT '''%'+ VALUE+ '%''' AS VALUE FROM [uf_SplitKeywords] (',', 'one,two,three'))

我希望在这方面的帮助。

对样品sqlFiddle由于某种原因,我不能够创造出我所提到的sqlFiddle功能。

Answer 1:

Alter FUNCTION [dbo].[uf_SplitKeywords] 
   (  @DELIMITER VARCHAR(5), 
      @LIST      VARCHAR(MAX) 
   ) 
   RETURNS @TABLEOFVALUES TABLE 
      (  ROWID   int IDENTITY(1,1), 
         [VALUE] VARCHAR(MAX) 
      ) 
AS 
   BEGIN
   Declare @Pos int
   While LEN(@List) > 0
      begin
        Select @Pos=CHARINDEX(@Delimiter,@List,1)      
        if @Pos>0
           begin
             Insert into @TABLEOFVALUES ([Value]) Values (SubString(@List,1,@Pos -1))
             Select @LIST = STUFF(@List,1,@Pos ,'')
           end
        else  
            begin
            Insert into @TABLEOFVALUES ([Value]) Values (@List)
            Select @LIST =''
            end  
      end
   Return 
   End

通过调用

Select Distinct b.ArticleID,b.Title,b.Description,b.Details,b.KeyWords from
(
Select * from Article a1 
CROSS APPLY [dbo].[uf_SplitKeywords](',',keywords) f1
Where a1.ArticleID=3
) a
Join
(
Select * from Article a2 
CROSS APPLY [dbo].[uf_SplitKeywords](',',keywords) f2
) b
on a.Value=b.Value


Answer 2:

如果我理解正确的话,你有一个“关键词”和“标签”的文章。 要显示与相同的“关键字”或“标签”相关的文章。

从概念上讲,你需要修改你的数据库表的设计。 除了插入关键字作为第一个表的varchar(100),你可以创建条款ArticleID INT为外键约束和另一列关键词为varchar新表Article_Keywords。

然后你就可以加入根据文章ID表。 所以Article_Keywords会是什么样子:

最佳实践解决方案

不要允许在ID列空值

alter TABLE Article
alter column ArticleID int not null

添加主键ID列索引和与其他表加入

alter TABLE Article
add constraint PK_ArticleID PRIMARY KEY (ArticleID)

创建新的表格文章关键词

create table Article_Keywords
(
    [ArticleID] int not null,
    [Keywords] nvarchar(100),
    Foreign key ([ArticleID]) References Article(ArticleID),
)

插入数据

insert into [Article_Keywords] Values (1,'one'),(1,'two'),(1,'three');
insert into [Article_Keywords] Values (2,'two'),(2,'three'),(2,'four');
insert into [Article_Keywords] Values (3,'three'),(3,'four'),(3,'five');
insert into [Article_Keywords] Values (4,'four'),(4,'five'),(4,'six'),(5,'two'),(5,'three'),(6,'eight'),(6,'nine'),(7,'nine'),(7,'ten'),(8,'eleven');

delete from Article_Keywords where [ArticleID] = [Keywords]

SELECT
    DISTINCT AK1.ArticleID
FROM Article_Keywords AK1
WHERE EXISTS (
SELECT AK2.Keywords from Article_Keywords AK2
WHERE AK2.[ArticleID] = 3 AND AK1.[KEYWORDS] = AK2.[KEYWORDS]
) 

不过,如果你觉得有必要下去你要的样子,你可以使用光标(不明智的):

创建一个临时表来存储所有相关文章

IF ( OBJECT_ID('tempdb.dbo.#RelatedArticles') IS NOT NULL ) DROP TABLE #RelatedArticles
CREATE TABLE #RelatedArticles (
    ArticleID int
);


DECLARE @VALUE NVARCHAR(100)
DECLARE Keyword_Cursor Cursor For

使用[uf_SplitKeywords]从文章表中提取的关键字

SELECT [Value] FROM [uf_SplitKeywords] (',',(SELECT [KEYWORDS] FROM ARTICLE WHERE ARTICLEID = 3))

OPEN Keyword_Cursor

FETCH NEXT FROM Keyword_Cursor into @VALUE

WHILE @@FETCH_STATUS = 0
BEGIN

    insert into #RelatedArticles
    SELECT [ArticleID] from Article
    where [keywords] like (SELECT '%' + @VALUE +  '%');

    FETCH NEXT FROM Keyword_Cursor into @VALUE
END

CLOSE Keyword_Cursor
DEALLOCATE Keyword_Cursor

SELECT DISTINCT ArticleID from #RelatedArticles

比较这两种方法,你会发现,设计复杂的项目时有一个更好的数据库设计会为你节省更多的时间。



文章来源: SELECT related articles based on keywords from single table