SQL - Как проверить, что хотя бы 1 ключевое слово из списка ключевых слов существует в поле - PullRequest
1 голос
/ 23 марта 2012

У меня есть таблица ключевых слов с полями KeywordsEn и KeywordsFr.У меня есть другой MediaObjectsMetadata с полем Значения.

Мне нужно проверить, что поле Значение содержит хотя бы одно из слов из таблицы Ключевые слова (либо в поле KeywordsEn, либо KeywordsFr).

IЯ подумал, что я бы использовал такую ​​функцию Contains, где @priorityKeywords содержит все ключевые слова и ключевые слова, объединенные с OR, но в моей строке более 16000 символов, а функция Contains может разрешить только 4000.

Частьмоей функции 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 #, которая генерирует @ 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;
}

Какое решение вы бы порекомендовали для моей хранимой процедуры?

Изменить (Решение):

Вот решение, предложенное 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)
        )

Ответы [ 3 ]

0 голосов
/ 23 марта 2012

Возможно, неэффективно, но стоит попробовать:

select * from MediaObjectsMetadata m
where exists 
(select null from Keywords k
 where m.values like '%' & k.KeywordEn & '%' or
       m.values like '%' & k.KeywordFr & '%' )
0 голосов
/ 23 марта 2012

Что вы думаете о том, чтобы хранимая процедура создала временную таблицу содержимого столбца, содержащего ключевое слово, а затем проверила, есть ли какое-либо пересечение между UNION двух списков и временной таблицей?

Это то, что вы знаете, как это сделать (вероятно, вам нужна определенная пользователем функция для разделения поля на таблицу), и если нет, то какую базу данных вы используете (извините, если в коде c # есть что-то, что должно давать подсказку меня, я не вижу)

0 голосов
/ 23 марта 2012

Если вы используете SQL Server 2008, вы можете использовать табличный параметр, чтобы передать список ключевых слов хранимой процедуре.Вы можете использовать переменную, как если бы вы использовали table, в предложении 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

РЕДАКТИРОВАТЬ: если у вас есть более одного ключевого слова в поле значения, вы можете использовать функцию разделения .Например:

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

Это требует, чтобы все ключевые слова в столбце значений (разделенные пробелом) присутствовали в параметре @list.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...