2010-12-23 24 views
7

Ok, usando SQL Server 2008. En mi página web tengo un cuadro de texto con jQuery-UI Autocompletado conectado.Procedimiento almacenado de T-SQL para devolver los resultados de búsqueda "sugeridos" del estilo de google

Ahora necesito un procedimiento almacenado para buscar en todas las columnas de una sola tabla (o varias tablas unidas, supongo) para una cadena de búsqueda proveniente de la llamada AJAX de cuadro de texto/autocompletar y devolver cadenas de búsqueda "sugeridas". Estoy utilizando el AdventureWorks DB para probar (tabla Products)

Por ejemplo, la tabla de productos tiene columnas para el nombre del producto y el número de producto (entre otros) y quiero devolver las cadenas de búsqueda sugeridas en función de la entrada del usuario donde puedan ingrese un nombre de producto y/o un número de producto.

Lo tengo trabajando en una sola columna que era simple. ¿Algunas ideas?

+0

Gracias a todos por los buenos comentarios y ejemplos. Todos tienen sus usos en diversas situaciones y puedo verme a mí mismo usando alguna forma de todos ellos en el futuro – stephen776

Respuesta

6

Voy a sugerir la búsqueda de texto completo (MS 'o Lucene funcionarán) El siguiente código utiliza MSSQL FTS como su uso en mi aplicación en este momento.

Instalar FTS Search si aún no lo ha hecho. Si tiene control, el servicio se está ejecutando. En el estudio de administración, ejecute esto para configurar un catálogo y agregar la tabla de productos; y Color/Nombre/Número de Producto para el catálogo.

USE [AdventureWorks] 
GO 
CREATE FULLTEXT CATALOG [ProductsTest]WITH ACCENT_SENSITIVITY = OFF 
AUTHORIZATION [dbo] 

GO 

USE [AdventureWorks] 
GO 
CREATE FULLTEXT INDEX ON [Production].[Product] KEY INDEX [PK_Product_ProductID] ON ([ProductsTest]) WITH (CHANGE_TRACKING AUTO) 
GO 
USE [AdventureWorks] 
GO 
ALTER FULLTEXT INDEX ON [Production].[Product] ADD ([Color]) 
GO 
USE [AdventureWorks] 
GO 
ALTER FULLTEXT INDEX ON [Production].[Product] ADD ([Name]) 
GO 
USE [AdventureWorks] 
GO 
ALTER FULLTEXT INDEX ON [Production].[Product] ADD ([ProductNumber]) 
GO 
USE [AdventureWorks] 
GO 
ALTER FULLTEXT INDEX ON [Production].[Product] ENABLE 
GO 

A continuación, puede ejecutar consultas contra todas las columnas a la vez; p.ej. Plata (elegido como en el color y nombre)

Select * from production.product where 
contains(*, '"Silver*"') 

El * en la consulta encontrarán plata * para que pueda usar esto para acumular resultados que el usuario escribe en. Una cosa a tener en cuenta es que Google a mejorar este trabaje en tiempo real: si está buscando una gran cantidad de datos, podrá recuperar los datos sin interrumpir la escritura del usuario. Creo que, en general, las personas usan estas búsquedas escribiendo desde la primera letra que están buscando (acepto errores ortográficos). Podrían implementar un corrector ortográfico después de cada espacio que presionen para manejarlo. O almacene las búsquedas que se ejecutan y observe los errores ortográficos y cambie el código para manejarlo en función de un mapeo (o en FTS usando un diccionario de sinónimos personalizado).)

La clasificación va a ser un problema de desarrollo divertido para cualquier empresa; ¿Encontraste el primer resultado para Mountain Frame? ¿O quieres ponderarlos por ventas o por precio? Si el usuario escribe más de un término de texto, puede usar FTS para generar una clasificación basada en la cadena de búsqueda.

select aa.rank, bb.* 
From containstable(production.product, *, '"Mountain" and "Silver*"') aa 
inner join production.product bb 
on aa.[key] = bb.productid 
order by rank desc 

Esto devuelve 30 filas; y ponderaciones basadas en el texto ingresado por el usuario para determinar el primer registro de lugar. En cualquier caso, es probable que desee agregar una clasificación codificada para modificar los resultados según sus deseos de negocios: clasificar el widget de mayor precio 1 podría no ser el camino. Es por eso que va a almacenar lo que la gente buscó/hizo clic para que pueda analizar los resultados más adelante.

Hay un muy buen language parser para .Net que traduce una consulta de cadena de estilo de google ingresada en el lenguaje FTS, que le proporciona familiaridad para cualquier búsqueda booleana que use su sitio.

Quizás desee agregar algo de sabiduría acerca de las funciones de multitudes al auditar en contra de lo que los usuarios ingresaron y finalmente visitar y usar los mapas de éxito para alterar las sugerencias finales y hacerlas relevantes para el usuario.

Como sugerencia final si se trata de un sitio web comercial es posible que desee mirar a Easyask que es un gran procesador de lenguaje natural miedo

+0

Sin duda lo tendré en cuenta.Gracias por el gran ejemplo – stephen776

+0

Después de leer más y otra pregunta ... esta puede ser una mejor solución ... investigar más ahora. gracias de nuevo – stephen776

2

Editar: Utilice un UNION para unirse a consultas separadas

SELECT productname FROM foo WHERE productname LIKE '%myinput%' 
UNION 
SELECT productnumber FROM foo WHERE productnumber LIKE '%myinput%' 
UNION 
... 

No hay forma automática para escanear todas las columnas a menos que utilice SQL dinámico

+0

, pero ¿qué pasa con la instrucción SELECT? Quiero buscar entre todas las columnas en la tabla/tablas y devolver una sola columna de valores coincidentes – stephen776

+1

¿Qué pasa con el voto a favor?!? –

+0

@Paul Sasik: mi primera respuesta no fue pensada ...? – gbn

3

Uso de la función soundex sería la forma más sencilla para que coincida para "artículos" similares en varias columnas. Pero un mejor algoritmo de coincidencia que será casi tan rápido de implementar es el Levenshtein Edit Distance. Aquí está el T-SQL implementation envuelto en una función. Úselo para que coincida con términos de búsqueda similares.

EDITAR Muestra de Levenshtien en la acción (basado en SQL de GBN)

Supongamos que usted designó a su Levenshtein T-SQL función LVN (aras de la brevedad solo lado a otro), entonces usted podría hacer algo como:

SELECT productname FROM foo WHERE productname 
    LIKE '%myinput%' OR lvn(myinput) < 3 
UNION 
SELECT productnumber FROM foo WHERE productnumber 
    LIKE '%myinput%' OR lvn(myinput) < 3 
UNION 
... 

ORDER BY 1 -- one-based column index sort for UNION queries 

Sí. así de simple. Por cierto, actualicé el enlace levenshtein de T-SQL a algo que tiene más sentido, y es una respuesta SO aceptada.

+0

¡increíble! Voy a verificar esto con seguridad. Esto debería ser exactamente lo que estoy buscando – stephen776

+0

sí, esto funciona muy bien. Puedo ver que esto es útil en una situación en la que uno está buscando algo así como números de productos en los que sería fácil escribir erróneamente 1 o más caracteres. – stephen776

+0

También es bueno para el corrector ortográfico y las búsquedas difusas. Levenshtein es definitivamente algo que quieres poner en tu bolsillo trasero. Es increíblemente portátil y útil. –

0

Tengo crear un SQL muestra que devolverá resultados de búsqueda Google estilo. Puede probar este T-SQL. También puede agregar más de un criterio de búsqueda en la columna de la tabla.

ALTER PROC [dbo].[USP_GetDoctorLookupList] 
(
    @SearchText varchar(50), 
    @ItemCount int 
) 
AS 
BEGIN 
    SET @SearchText = RTRIM(@SearchText) + '%' 
    BEGIN 
     SELECT TOP (@ItemCount) * 
     FROM 
     (
      SELECT 
       CASE 
        WHEN RTRIM(LTRIM(d.cdocname)) LIKE @SearchText then 1 
        WHEN RTRIM(LTRIM(d.cdeano)) LIKE @SearchText then 2 

       END OrderBy, 
       d.docid_PK, 
       d.cdocname, 
       d.cdeano 

      FROM doctor d 

      WHERE 
       (d.cdocname LIKE @SearchText 
       OR d.cdeano LIKE @SearchText 
       ) 
     ) Doc ORDER BY OrderBy, cdocname 
    END 
END 
Cuestiones relacionadas