複数のテーブル、列にまたがるSQL Server 2008のフルテキスト検索の使用
-
03-07-2019 - |
質問
全文検索を使用して、データベース内の2つのテーブルから複数の列を検索する必要があります。問題の2つのテーブルには、フルテキストインデックスが作成された関連列があります。
全文検索を選択する理由: 1.アクセント付きの単語を簡単に検索できるようにする(cafè) 2.単語の近接度などに従ってランク付けできるようにする。 3.「XXXを意味しますか?」機能
課題を説明するために、ダミーのテーブル構造を次に示します。
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)
ブック名、ブックノート、著者名を検索する必要があります。
これを達成する2つの方法を知っています:
-
フルテキストインデックス付きビューの使用:これは私の好みの方法でしたが、フルテキストインデックス化されるビューでは、スキーマバインドされ、外部結合がなく、一意のインデックスがあります。データを取得するのに必要なビューは、これらの制約を満たしていません(データを取得する必要がある他の多くの結合テーブルが含まれています)。
-
ストアドプロシージャでの結合の使用:このアプローチの問題は、結果をランクでソートする必要があることです。テーブル間で複数の結合を行っている場合、SQL Serverはデフォルトで複数のフィールドを検索しません。 2つのリンクテーブルで2つの個別のCONTAINSクエリを組み合わせることができますが、2つの検索クエリから combined ランクを抽出する方法がわかりません。たとえば、「Arthur」を検索する場合、BookクエリとAuthorクエリの両方の結果を考慮し、それに応じて重み付けする必要があります。
解決
FREETEXTTABLEを使用すると、結合された各テーブル結果の結合ランクを計算するアルゴリズムを設計するだけで済みます。以下の例では、本の表からのヒットに向かって結果を歪めています。
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
この例ではスキーマを単純化したことに注意してください。
他のヒント
私はあなたと同じ問題を抱えていましたが、実際には10個のテーブル(Usersテーブルと他のいくつかの情報)が含まれていました
各テーブルのWHERE句でFREETEXTを使用して最初のクエリを実行しましたが、クエリに時間がかかりすぎていました。
次に、代わりにFREETEXTTABLEを使用し、各テーブルのキー列でnull以外の値をチェックすることについていくつかの応答を見ましたが、実行にも時間がかかりました。
FREETEXTTABLEとUNIONの選択の組み合わせを使用して修正しました:
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
これは非常に高速であることが証明されました。
お役に立てば幸いです。
受け入れられた答えが問題を解決するとは思わない。特定の著者のすべての書籍を検索し、そのため著者の名前(またはその一部)を検索条件として使用しようとすると、クエリによって返される書籍は、独自の名前の検索条件を持つ書籍のみになります。 。
この問題を回避する唯一の方法は、Bookテーブルで検索したい著者の列を複製し、それらの列(または列は著者の関連情報をXML列に保存するのが賢明なのでおそらく列にインデックスを付けることです) Bookテーブルで)。
FWIW、同様の状況で、DBAは専用の全文検索テーブルを維持するためにDMLトリガーを作成しました。マテリアライズドビューは多くの制限のため使用できませんでした。
ストアドプロシージャを使用します。フルテキストメソッド、または並べ替え可能なランクを返すもの。それらがお互いにどのように重み付けされるかはわかりませんが、しばらくの間いじってそれを理解できると確信しています。例:
Select SearchResults.key, SearchResults.rank From FREETEXTTABLE(myColumn, *, @searchString) as SearchResults Order By SearchResults.rank Desc
この回答はかなり遅れていますが、プライマリテーブルを変更できない場合にこれを行う1つの方法は、1つの列に検索パラメーターを追加して新しいテーブルを作成することです。
次に、その列に全文索引を作成し、その列を照会します。
例
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
[EAN]。[dbo]。[tblEanFullTextSearch]の上のコードでは、FullTextSearchColumnはフィールドが追加された新しいテーブルと列であり、表示したいテーブルへの結合を使用して新しいテーブルでクエリを実行できます。からのデータ。
これが役立つことを願って