我正在制作一个网页项目,其中显示其中一个页面的文章详情,另外我还需要根据keywords
或tags
显示前5个相关文章。
我不确定如何使用T-SQL完全做到这一点,而不是从后面的代码中进行部分处理。
我使用FUNCTION来分割我的关键字并将结果传递给其他查询以获得对我不起作用的所需结果。
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上提到的FUNCTION。
答案 0 :(得分: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
答案 1 :(得分:1)
如果我理解正确,您的文章中包含“关键字”和“代码”。您希望使用相同的“关键字”或“代码”显示相关文章。
从概念上讲,您需要修改数据库表的设计。您可以创建新表Article_Keywords,而不是在Article表中插入关键字作为varchar(100) 使用ArticleID int作为外键约束,将另一列作为varchar。
然后,您可以根据文章ID加入表格。所以Article_Keywords看起来像:
alter TABLE Article
alter column ArticleID int not null
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
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
比较这两种方法,您会发现在设计复杂项目时,拥有更好的数据库设计将为您节省更多时间。