1

私は、そのページの 1 つに記事の詳細を表示する Web プロジェクトに取り組んでおり、keywordsまたはに基づいて上位 5 つの関連記事を表示する必要もありtagsます。

コードビハインドから処理の一部を行うのではなく、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 を作成できません。

4

2 に答える 2

1

私の理解が正しければ、「キーワード」と「タグ」を含む記事があります。「キーワード」や「タグ」が同じ関連記事を表示したい。

概念的には、データベース テーブルの設計を変更する必要があります。Article テーブルに varchar(100) として Keywords を挿入する代わりに、ArticleID int を外部キー制約として、別の列 Keywords を varchar として新しいテーブル Article_Keywords を作成できます。

次に、記事 ID に基づいてテーブルを結合できます。したがって、Article_Keywords は次のようになります。

ベスト プラクティス ソリューション

ID 列に Null を許可しない

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] を使用して、Article テーブルからキーワードを抽出します

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

2 つの方法を比較すると、複雑なプロジェクトを設計するときに、より優れたデータベース設計を使用すると、より多くの時間を節約できることがわかります。

于 2013-01-23T07:01:40.000 に答える
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
于 2013-01-23T06:56:57.860 に答える