Pergunta

Eu preciso pesquisar em várias colunas de duas tabelas no meu banco de dados usando Full-Text Search. As duas tabelas em questão têm a colunas relevantes full-text indexado.

A razão que eu estou optando por pesquisa de texto completo: 1. Para ser capaz de pesquisar palavras acentuadas facilmente (CAFE) 2. Para ser capaz de classificação de acordo com a proximidade palavra, etc. 3. "Você quis dizer XXX?" funcionalidade

Aqui é um manequim estrutura da tabela, para ilustrar o desafio:

Table Book
BookID
Name (Full-text indexed)
Notes (Full-text indexed)

Table Shelf
ShelfID
BookID

Table ShelfAuthor
AuthorID
ShelfID

Table Author
AuthorID
Name (Full-text indexed)

Eu preciso pesquisar em Nome Livro, Livro Notes e Nome do Autor.

Eu sei de duas maneiras para fazer isso:

  1. Usando um índice de texto total Ver: Este teria sido o meu método preferido, mas não posso fazer isso porque para uma visão a ser indexado por texto total, ele precisa ser schemabound, não tem qualquer junções externas, tem um índice exclusivo. A visão que eu vai precisar de ter os meus dados não satisfazem essas restrições (que contém muitas outras tabelas associadas que eu preciso para obter dados a partir de).

  2. Usando junta-se em um procedimento armazenado : O problema com esta abordagem é que eu preciso ter os resultados classificado por categoria. Se eu estou fazendo várias associações através das tabelas, SQL Server não irá pesquisar em vários campos por padrão. Eu posso combinar duas individuais contém consultas sobre as duas tabelas ligadas, mas eu não sei de uma maneira de extrair o combinado classificação das duas consultas de pesquisa. Por exemplo, se eu procurar 'Arthur', os resultados de ambos a consulta Livro e da consulta Autor devem ser levados em conta e ponderados em conformidade.

Foi útil?

Solução

Usando FREETEXTTABLE, você só precisa criar um algoritmo para calcular a classificação incorporada em cada resultado tabela associada. O exemplo abaixo skews o resultado em direção sucessos da tabela do livro.

SELECT b.Name, a.Name, bkt.[Rank] + akt.[Rank]/2 AS [Rank]
FROM Book b
INNER JOIN Author a ON b.AuthorID = a.AuthorID
INNER JOIN FREETEXTTABLE(Book, Name, @criteria) bkt ON b.ContentID = bkt.[Key] 
LEFT JOIN FREETEXTTABLE(Author, Name, @criteria) akt ON a.AuthorID = akt.[Key]
ORDER BY [Rank] DESC

Note que eu simplifiquei o esquema para este exemplo.

Outras dicas

Eu tive o mesmo problema que você, mas ele realmente envolveu 10 tabelas (uma tabela de usuários e vários outros para informações)

Eu fiz a minha primeira consulta usando FREETEXT na cláusula WHERE para cada mesa, mas a consulta estava tomando muito tempo.

Então eu vi várias respostas sobre o uso FREETEXTTABLE vez e verificação de não anula os valores na coluna chave para cada mesa, mas que também tomou muito tempo para executar.

eu fixa-lo usando uma combinação de FREETEXTTABLE e UNIÃO selecciona:

SELECT Users.* FROM Users INNER JOIN
(SELECT Users.UserId FROM Users INNER JOIN FREETEXTTABLE(Users, (column1, column2), @variableWithSearchTerm) UsersFT ON Users.UserId = UsersFT.key
UNION
SELECT Table1.UserId FROM Table1 INNER JOIN FREETEXTTABLE(Table1, TextColumn, @variableWithSearchTerm) Table1FT ON Table1.UserId = Table1FT.key
UNION
SELECT Table2.UserId FROM Table2 INNER JOIN FREETEXTTABLE(Table2, TextColumn, @variableWithSearchTerm) Table2FT ON Table2.UserId = Table2FT.key
... --same for all tables
) fts ON Users.UserId = fts.UserId

Isto provou ser incrivelmente muito mais rápido.

Espero que ajude.

Eu não acho que a resposta aceita vai resolver o problema. Se você tentar encontrar todos os livros a partir de um determinado autor e, portanto, usar o nome do autor (ou parte dele) como critério de pesquisa, os únicos livros devolvidos pela consulta serão aqueles que têm os critérios de pesquisa em seu próprio nome .

A única maneira que eu vejo em torno deste problema é replicar colunas do autor de que pretende procurar por na tabela Livro e índice essas colunas (ou coluna, uma vez que provavelmente seria inteligente para armazenar informações relevantes do autor em uma coluna XML na tabela Book).

FWIW, em uma situação semelhante a nossa DBA criado gatilhos DML para manter uma tabela de pesquisa dedicado de texto completo. Não foi possível usar uma visão materializada por causa de suas muitas restrições.

Gostaria de usar um procedimento armazenado. O método de texto completo ou o que quer que retorna um ranking que você pode classificar por. Eu não sei como eles vão ser ponderados contra eachother, mas eu tenho certeza que você poderia mexer por algum tempo e descobrir isso. Por exemplo:

Select SearchResults.key, SearchResults.rank From FREETEXTTABLE(myColumn, *, @searchString) as SearchResults Order By SearchResults.rank Desc

Esta resposta é bem atrasado, mas uma maneira de fazer isso se você não pode modificar tabelas primárias é criar uma nova tabela com os parâmetros de pesquisa adicionados a uma coluna.

Em seguida, criar um índice de texto completo nessa coluna e consulta dessa coluna.

Exemplo

SELECT 
    FT_TBL.[EANHotelID]                 AS HotelID, 
    ISNULL(FT_TBL.[Name],'-')           AS HotelName,
    ISNULL(FT_TBL.[Address1],'-')       AS HotelAddress,
    ISNULL(FT_TBL.[City],'-')           AS HotelCity,
    ISNULL(FT_TBL.[StateProvince],'-')  AS HotelCountyState,
    ISNULL(FT_TBL.[PostalCode],'-')     AS HotelPostZipCode,
    ISNULL(FT_TBL.[Latitude],0.00)      AS HotelLatitude,
    ISNULL(FT_TBL.[Longitude],0.00)     AS HotelLongitude,
    ISNULL(FT_TBL.[CheckInTime],'-')    AS HotelCheckinTime,
    ISNULL(FT_TBL.[CheckOutTime],'-')   AS HotelCheckOutTime,
    ISNULL(b.[CountryName],'-')         AS HotelCountry,
    ISNULL(c.PropertyDescription,'-')   AS HotelDescription,
    KEY_TBL.RANK 

    FROM [EAN].[dbo].[tblactivepropertylist] AS FT_TBL INNER JOIN
     CONTAINSTABLE ([EAN].[dbo].[tblEanFullTextSearch], FullTextSearchColumn, @s)
      AS KEY_TBL
    ON FT_TBL.EANHotelID = KEY_TBL.[KEY]
    INNER JOIN [EAN].[dbo].[tblCountrylist] b
    ON FT_TBL.Country = b.CountryCode
    INNER JOIN [EAN].[dbo].[tblPropertyDescriptionList] c
    ON FT_TBL.[EANHotelID] = c.EANHotelID

No código acima [EAN]. [Dbo]. [TblEanFullTextSearch], FullTextSearchColumn é a nova tabela e coluna com os campos adicionados, agora você pode fazer uma consulta sobre a nova tabela com junta-se à mesa que você deseja exibir os dados do.

Espero que isso ajude

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top