簡體   English   中英

跨多個表的SQL簡單搜索功能

[英]SQL simple search functionality across multiple tables

我正在使用SQL Server2012。我需要使用單個文本字段實現搜索功能。

假設我有下表:

--------------------------------------------------------------------------------
FIRSTNAME   LASTNAME    CITY        PROMOYEAR   EMPLOYOR    
--------------------------------------------------------------------------------
John        Doe         Boston      2005        Mc Donald   
Marc        Forestier   Bruxelle    2010        Private bank    
Céline      Durand      Paris       1999        Food SA     
Simon       Forestier   Toulouse    2001        Forestier SARL  
John        Smith       New York    1992        Events Org. 
Sonia       Grappe      Toulon      2010        Forestier SARL  
--------------------------------------------------------------------------------

行為如下:

  • 必須在所有列中搜索所有單詞(以空格分隔)。
  • 每個單詞都應使用LIKE
  • 如果僅搜索一個單詞,則返回包含該單詞的所有記錄
  • 如果搜索到多個單詞,則僅返回包含最大數量的不同單詞的記錄(請參見下面的“ forestier”示例)
  • 我只需要一個查詢 ,不需要TSQL

我嘗試了很多事情,但這並不像看起來那么簡單。

一些例子:

“約翰”:

-------------------------------------------------------------------------------
FIRSTNAME   LASTNAME    CITY        PROMOYEAR   EMPLOYOR
-------------------------------------------------------------------------------
John        Doe         Boston      2005        Mc Donald
John        Smith       New York    1992        Events Org.
-------------------------------------------------------------------------------

“約翰·多伊”:

-------------------------------------------------------------------------------
FIRSTNAME   LASTNAME    CITY        PROMOYEAR   EMPLOYOR
-------------------------------------------------------------------------------
John        Doe         Boston      2005        Mc Donald
-------------------------------------------------------------------------------

“弗賴斯”:

-------------------------------------------------------------------------------
FIRSTNAME   LASTNAME    CITY        PROMOYEAR   EMPLOYOR
-------------------------------------------------------------------------------
Marc        Forestier   Bruxelle    2010        Private bank
Simon       Forestier   Toulouse    2001        Forestier SARL
Sonia       Grappe      Toulon      2010        Forestier SARL
-------------------------------------------------------------------------------

“ 2010年xelle”:

FIRSTNAME   LASTNAME    CITY        PROMOYEAR   EMPLOYOR
--------------------------------------------------------------------------------
Marc        Forestier   Bruxelle    2010        Private bank
--------------------------------------------------------------------------------

這個例子使用一個表。 實際上,我的5列來自4個不同的表,因此實現全文搜索要稍微復雜一點!

如何添加另一個字段,例如包含其他字段中所有信息的文本字段。

FIRSTNAME   LASTNAME    CITY        PROMOYEAR   EMPLOYOR   SEARCHFIELD
John        Doe         Boston      2005        Mc Donald  John Doe Boston 2005 Mc Donald

並在此字段上進行搜索。 它不是很優雅,但是可以工作。

在下面添加:

我認為SQL語法不能滿足您的所有需求,但您可以采取其他解決方法。 創建一個包含所有要搜索的單詞的表:

create table searchtable
(
rowid int, --key to the id for the row in your table
mothertableName varchar(), -- name of the table if necessary
motherfieldName varchar(), -- name of field
word varchar() -- the actual word to be searchable
)

搜索單詞及其出現次數最多的地方:

SELECT * FROM myTable WHERE id IN(
   SELECT rid as id, MAX(c) FROM (
      SELECT rowid as rid, COUNT(rowid) as c FROM Searchtable WHERE word IN ('john','doe')
   )
)

上面的SQL肯定不會起作用,但是希望您對我的建議有所了解。 您應該獲得最多搜索詞的一行。 但是SQL中的“ IN”運算符要求您動態創建一些SQL。

當您寫到您已經嘗試了幾乎所有內容時,我認為SQL不能獨自完成。

這似乎是Sql全文索引設計的工作。

AFAIK全文索引不適用於數字類型,因此您可能需要為任何日期或數字類型添加計算列,例如,如果PromoYear為數字:

ALTER TABLE MyTable
   ADD TextPromoYear AS CAST(PromoYear AS NVARCHAR(4))
   PERSISTED;

您需要在數據庫中設置全文目錄:

CREATE FULLTEXT CATALOG CAT_MyCat AS DEFAULT;

假設您有一個名為PK_MyTable的主鍵,請創建全文索引:

CREATE FULLTEXT INDEX ON MyTable(FirstName, LastName, City, TextPromoYear, 
                                 Employer) 
KEY INDEX PK_MyTable;
幸運的話,您將可以使用[`CONTAINS`](http://technet.microsoft.com/zh-cn/library/ms187787.aspx)或`FREETEXT`執行查詢,例如:SELECT * FROM mytable WHERE CONTAINS((FirstName,LastName,City,TextPromoYear,Employer),'for OR 2010 OR xelle')查詢語法不是您想要的語法,但是您可以使用'空格分隔的'查詢要根據`CONTAINS`進入`和`。

編輯

這不是那么容易。 通配符*只能用作后綴,並且您還需要匯總列以在所有列中進行搜索。

完整條款:

SELECT *
FROM mytable
WHERE CONTAINS(*, 'John and Doe');

對於部分搜索,您可能需要求助於使用香草的LIKE來測試未知前綴(*xelle)

SELECT *
FROM mytable
WHERE CONTAINS(*, '"for*"  and 2010') AND SearchableComputedColumn like '%elle%';

在這里更新了SqlFiddle

這是一個解決方案。

我已將搜索范圍限制為6個字。 對於每個單詞,我檢查它是否存在於串聯的列中。 每當在其中找到一個單詞時,我都會在+1上加上一個“分數”。 我返回得分最高的記錄。

功能 :

CREATE FUNCTION [dbo].[SEARCH_SINGLE] (
    @langId INT = 4,
    @searchString VARCHAR(MAX) = NULL
)
RETURNS TABLE
AS
RETURN
WITH words AS (
    SELECT Name as Val, ROW_NUMBER() OVER(ORDER BY Name) as Num FROM [dbo].splitstring(@searchString, ' ')
),
results AS (
    SELECT DISTINCT
        ...
        CASE WHEN EXISTS(SELECT 1 FROM words WHERE Num = 1 AND (ISNULL(a.[FIRSTNAME], '') + ' ' + ISNULL(a.[LASTNAME], '') + ' ' + ISNULL(c.[CITY], '') + ' ' + ISNULL(j.[PROMO_YEAR], '') + ' ' + ISNULL(e.[EMPLOYOR], '')) like '%'+Val+'%') THEN 1 ELSE 0 END +
        CASE WHEN EXISTS(SELECT 1 FROM words WHERE Num = 2 AND (ISNULL(a.[FIRSTNAME], '') + ' ' + ISNULL(a.[LASTNAME], '') + ' ' + ISNULL(c.[CITY], '') + ' ' + ISNULL(j.[PROMO_YEAR], '') + ' ' + ISNULL(e.[EMPLOYOR], '')) like '%'+Val+'%') THEN 1 ELSE 0 END +
        CASE WHEN EXISTS(SELECT 1 FROM words WHERE Num = 3 AND (ISNULL(a.[FIRSTNAME], '') + ' ' + ISNULL(a.[LASTNAME], '') + ' ' + ISNULL(c.[CITY], '') + ' ' + ISNULL(j.[PROMO_YEAR], '') + ' ' + ISNULL(e.[EMPLOYOR], '')) like '%'+Val+'%') THEN 1 ELSE 0 END +
        CASE WHEN EXISTS(SELECT 1 FROM words WHERE Num = 4 AND (ISNULL(a.[FIRSTNAME], '') + ' ' + ISNULL(a.[LASTNAME], '') + ' ' + ISNULL(c.[CITY], '') + ' ' + ISNULL(j.[PROMO_YEAR], '') + ' ' + ISNULL(e.[EMPLOYOR], '')) like '%'+Val+'%') THEN 1 ELSE 0 END +
        CASE WHEN EXISTS(SELECT 1 FROM words WHERE Num = 5 AND (ISNULL(a.[FIRSTNAME], '') + ' ' + ISNULL(a.[LASTNAME], '') + ' ' + ISNULL(c.[CITY], '') + ' ' + ISNULL(j.[PROMO_YEAR], '') + ' ' + ISNULL(e.[EMPLOYOR], '')) like '%'+Val+'%') THEN 1 ELSE 0 END +
        CASE WHEN EXISTS(SELECT 1 FROM words WHERE Num = 6 AND (ISNULL(a.[FIRSTNAME], '') + ' ' + ISNULL(a.[LASTNAME], '') + ' ' + ISNULL(c.[CITY], '') + ' ' + ISNULL(j.[PROMO_YEAR], '') + ' ' + ISNULL(e.[EMPLOYOR], '')) like '%'+Val+'%') THEN 1 ELSE 0 END as Nb
    FROM
        ...
    WHERE
        ...
)
SELECT 
    ...
FROM
    results
WHERE
    Nb = (SELECT MAX(Nb) FROM results)
    AND Nb <> 0

評論?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM