2012-03-23 1 views
1

フィールドKeywordsEnとKeywordsFrを持つKeywordsテーブルがあります。 私は値フィールドを持つ別のMediaObjectsMetadataを持っています。SQL - キーワードのリストから少なくとも1つのキーワードがフィールドに存在することを確認する方法

「値」フィールドにキーワードテーブルの単語(KeywordsEnまたはKeywordsFrフィールドのいずれか)が少なくとも1つ含まれていることを確認する必要があります。

は私が@priorityKeywordsはORで連結すべてKeywordsEnとKeywordsFrが含まれています。このような機能を、含まれて使用するだろうと思ったが、その後私は、文字列で16000以上の文字があり、機能のみを許可することができます含まれて4000

@priorityKeywords何ソリューションはあなたでしょう

public static string GetPriorityKeywordsList() 
{ 
    string keywordString = String.Empty; 

    using (IDataReader dr = GetCommandPriorityKeywordsList().ExecuteReader(CommandBehavior.CloseConnection)) 
    { 
    while (dr.Read()) 
    { 
     if (keywordString.Length > 0) 
     { 
     keywordString += " OR "; 
     } 
     // max 4000 chars allowed in COntains sql function of sp 
     keywordString += "'" + dr["KeywordEn"].ToString() + "' OR '" + dr["KeywordFr"].ToString() + "'"; 
    } 
    } 
     return keywordString; 
} 

を生成し、私のSP

SELECT FKMediaObjectId 
FROM dbo.gs_MediaObjectMetadata 
WHERE UPPER([Description]) = 'KEYWORDS' 
AND FKMediaObjectId >= 
    (SELECT TOP 1 MediaObjectId 
    FROM dbo.gs_MediaObject 
    WHERE DateAdded > @lastcheck 
    ORDER BY MediaObjectId) 
    AND Contains([Value] , @priorityKeywords); 

C#関数の

パート私のストアドプロシージャをお勧めしますか?

編集(ソリューション):ここで

が私の状況に適応し、Andomarによって提案されたソリューションです:

select * 
from gs_MediaObjectMetadata yt 
where 
UPPER([Description]) = 'KEYWORDS' 
AND not exists 
     (
     select * 
     from dbo.fnSplit(Replace(yt.Value, '''', ''''''), ',') split 
     where split.item in (select KeywordEn from gs_Keywords) or split.item in (select KeywordFr from gs_Keywords) 
     ) 
+0

多分、SQLを複数回実行して、文字列を4000文字の制限のままにして、結果に加わることができますか? –

+0

私は、パフォーマンスが最高になる理想的なソリューションがあるかどうかを知りたいと思います。これを実行するための多くのレコードがあります(これは非常に大きな写真アルバムです)。 – crichard

答えて

0

SQL Server 2008を使用している場合は、テーブル値パラメーターを使用することができますストアドプロシージャにキーワードのリストを渡します。変数、joinまたはin節のように変数を使用できます。たとえば、次のように

use testdatabase 
go 
if exists (select * from sys.procedures where name = 'TestProc') 
    drop procedure TestProc 
if exists (select * from sys.types where name = 'TestProcList') 
    drop type TestProcList 
go 
create type TestProcList as table (keyword varchar(50)) 
go 
create procedure dbo.TestProc(
    @list TestProcList readonly) 
as 
select * 
from YourTable 
where value in (select keyword from @list) 
go 

EDIT:あなたが値フィールドに複数のキーワードを持っている場合、あなたはsplit functionを使用することができます。例えば:

select * 
from YourTable yt 
where not exists 
     (
     select * 
     from dbo.fnSplit(yt.value, " ") split 
     where split.item not in (select keyword from @list) 
     ) 

これは(空白で区切られた)値列内のすべてのキーワードが@listパラメータに存在することを要求します。

+0

ああ、値フィールドに複数のキーワードがある可能性があります。この場合、この解決法は機能しません... – crichard

+0

I Keyフィールドにキーワードが1つ以上存在する必要がありますが、必ずしもすべてではありません。 – crichard

+0

素晴らしい作品です。ありがとう! – crichard

0

はおそらくうまく行ったが、試してみる価値があるかもしれません。

select * from MediaObjectsMetadata m 
where exists 
(select null from Keywords k 
where m.values like '%' & k.KeywordEn & '%' or 
     m.values like '%' & k.KeywordFr & '%') 
+0

LIKEキーワードは、FullTextを使用していますか? –

0

ストアドプロシージャを持っていることについてどう思いますかは、場合見て、キーワードが含まれている列の内容の一時テーブルを作成します2つのリストのUNIONと一時テーブルの間に交差点はありますか?

これは、フィールドをテーブルに分割するユーザー定義関数が必要な場合があります。そうでない場合は、どのデータベースバックエンドを使用していますか(C#コードに何かがある場合はごめんなさい私はそれを見ていません)

関連する問題