Pregunta

Necesito buscar en varias columnas de dos tablas en mi base de datos usando la búsqueda de texto completo. Las dos tablas en cuestión tienen las columnas relevantes indexadas a texto completo.

La razón por la que estoy optando por la búsqueda de texto completo: 1. Ser capaz de buscar fácilmente palabras acentuadas (cafè). 2. Poder clasificar según la proximidad de la palabra, etc. 3. " ¿Quiso decir XXX? & Quot; funcionalidad

Aquí hay una estructura de tabla ficticia , para ilustrar el desafío:

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)

Necesito buscar en el Nombre del libro, Notas del libro y Nombre del autor

Sé de dos maneras de lograr esto:

  1. Uso de una vista indizada de texto completo: Este hubiera sido mi método preferido, pero no puedo hacer esto porque para que una vista esté indexada a texto completo, es necesario Sea intrigable, no tenga ninguna combinación externa, tenga un índice único. La vista que necesitaré para obtener mis datos no satisface estas restricciones (contiene muchas otras tablas unidas de las que necesito obtener datos).

  2. Uso de uniones en un procedimiento almacenado : el problema con este enfoque es que necesito tener los resultados ordenados por rango. Si estoy realizando varias uniones en las tablas, SQL Server no buscará en múltiples campos de forma predeterminada. Puedo combinar dos consultas individuales de CONTAINS en las dos tablas vinculadas, pero no conozco una forma de extraer el rango combinado de las dos consultas de búsqueda. Por ejemplo, si busco 'Arthur', los resultados tanto de la consulta del Libro como de la consulta del Autor deberían tenerse en cuenta y ponderarse en consecuencia.

¿Fue útil?

Solución

Usando FREETEXTTABLE, solo necesitas diseñar un algoritmo para calcular el rango combinado en cada resultado de la tabla combinada. El siguiente ejemplo desvía el resultado hacia los resultados de la tabla de libros.

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

Tenga en cuenta que simplifiqué su esquema para este ejemplo.

Otros consejos

Tuve el mismo problema que tú, pero en realidad incluía 10 tablas (una tabla de Usuarios y varias otras para obtener información)

Hice mi primera consulta con FREETEXT en la cláusula WHERE para cada tabla, pero la consulta tardó demasiado.

Luego vi varias respuestas sobre el uso de FREETEXTTABLE en su lugar y la verificación de valores no nulos en la columna de clave para cada tabla, pero que también tardaron mucho en ejecutarse.

Lo arreglé utilizando una combinación de FREETEXTTABLE y UNION 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

Esto demostró ser increíblemente mucho más rápido.

Espero que ayude.

No creo que la respuesta aceptada solucione el problema. Si trata de encontrar todos los libros de un autor determinado y, por lo tanto, usa el nombre del autor (o parte de él) como criterio de búsqueda, los únicos libros devueltos por la consulta serán aquellos que tengan los criterios de búsqueda en su propio nombre. .

La única forma de solucionar este problema es replicar las columnas del autor que desea buscar en la tabla Libro e indexar esas columnas (o columna, ya que probablemente sería inteligente almacenar la información relevante del autor en una columna XML). en la tabla de libros).

FWIW, en una situación similar, nuestro DBA creó activadores DML para mantener una tabla de búsqueda de texto completo dedicada. No fue posible utilizar una vista materializada debido a sus muchas restricciones.

Yo usaría un procedimiento almacenado. El método de texto completo o lo que sea devuelve un rango que puede ordenar por. No estoy seguro de cómo se compararán entre sí, pero estoy seguro de que usted podría jugar un poco y resolverlo. Por ejemplo:

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

Esta respuesta está muy atrasada, pero una forma de hacerlo si no puede modificar las tablas primarias es crear una nueva tabla con los parámetros de búsqueda agregados a una columna.

Luego, crea un índice de texto completo en esa columna y consulta esa columna.

Ejemplo

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

En el código de arriba [EAN]. [dbo]. [tblEanFullTextSearch], FullTextSearchColumn es la nueva tabla y columna con los campos agregados, ahora puede hacer una consulta en la nueva tabla con combinaciones a la tabla que desea mostrar los datos de.

Espero que esto ayude

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top