2008-12-31 36 views
13

Tôi cần phải tìm kiếm trên nhiều cột từ hai bảng trong cơ sở dữ liệu của tôi bằng Tìm kiếm Toàn văn bản. Hai bảng được đề cập có các cột có liên quan toàn văn được lập chỉ mục.Sử dụng Tìm kiếm Toàn văn bản trong SQL Server 2008 trên nhiều bảng, cột

Lý do tôi chọn cho tìm kiếm văn bản đầy đủ: 1. Để có thể tìm kiếm từ có dấu dễ dàng (CAFE) 2. Để có thể để xếp hạng theo lời gần gũi vv 3. "Did ý anh là XXX? " chức năng

Đây là một cấu trúc bảng giả, để minh họa cho thách thức:

 
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) 

tôi cần phải tìm kiếm trên danh sách, Sách Notes và Author Name.

Tôi biết trong hai cách để thực hiện điều này:

  1. Sử dụng một văn bản đầy đủ Indexed Xem: Đây có thể là phương pháp ưa thích của tôi, nhưng tôi không thể làm điều này bởi vì đối với một cái nhìn để được toàn văn chỉ mục, nó cần phải được schemabound, không có bất kỳ tham gia bên ngoài, có một chỉ số duy nhất. Khung nhìn tôi sẽ cần để lấy dữ liệu của mình không đáp ứng các ràng buộc này (nó chứa nhiều bảng được nối khác mà tôi cần để lấy dữ liệu từ).

  2. Sử dụng kết nối theo thủ tục được lưu trữ: Vấn đề với cách tiếp cận này là tôi cần có kết quả được sắp xếp theo thứ hạng. Nếu tôi đang thực hiện nhiều phép nối trên các bảng, SQL Server sẽ không tìm kiếm trên nhiều trường theo mặc định. Tôi có thể kết hợp hai truy vấn CONTAINS riêng lẻ trên hai bảng được nối kết, nhưng tôi không biết cách nào để trích xuất các xếp hạng kết hợp từ hai truy vấn tìm kiếm. Ví dụ: nếu tôi tìm kiếm 'Arthur', kết quả của cả truy vấn Sách và truy vấn Tác giả sẽ được xem xét và cân nhắc tương ứng.

+0

Đối với # 1, nơi bạn nói bạn tham gia ... bạn có thực sự tham gia OUTER không? đó là một sản phẩm Descartes và tôi nghi ngờ bạn đang thực sự làm điều đó. Một bên trong hoặc trái/phải tham gia là tốt. –

+0

Tôi không sử dụng OUTER JOIN cho bất kỳ bảng được hiển thị nào. Có các bảng khác mà tôi cần để LEFT OUTER JOIN, vì chúng có thể không có bất kỳ hàng FKed nào. –

Trả lời

14

Sử dụng FREETEXTTABLE, bạn chỉ cần thiết kế một số thuật toán để tính toán thứ hạng sáp nhập trên mỗi kết quả bảng tham gia. Ví dụ bên dưới nghiêng kết quả về số lần truy cập từ bảng sách.

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 

Lưu ý rằng tôi đã đơn giản hóa giản đồ của bạn cho ví dụ này.

+0

Tha thứ cho tôi nếu tôi sai, nhưng không phải ở trên có nghĩa là kết quả sẽ chỉ được hiển thị cho bảng Tác giả nếu một AuthorID cũng xuất hiện trong một trong các kết quả hàng cho Sách? –

+0

Đúng vậy. Nếu đó là trường hợp tác giả xuất hiện không có sách, bạn sẽ cần phải điều chỉnh các kết hợp cho phù hợp. – Ishmael

+2

Không chắc chắn cách khả thi 'thiết kế một số thuật toán để tính toán thứ hạng đã kết hợp' là. [Tài liệu] (https://technet.microsoft.com/en-us/library/cc879245.aspx) cho biết: "Giá trị xếp hạng cho biết ** chỉ có thứ tự liên quan của các hàng trong tập kết quả **, với giá trị thấp hơn cho biết mức độ liên quan thấp hơn. Các giá trị thực tế không quan trọng và thường khác nhau mỗi khi truy vấn được chạy. " Bạn sẽ phải bình thường hóa công thức xếp hạng (OKAPI BM25) có vẻ không rõ ràng vì các giá trị xếp hạng tuyệt đối sẽ thay đổi với số liệu thống kê chỉ mục cơ bản. – Serguei

1

Tôi sẽ sử dụng quy trình được lưu trữ. Phương thức toàn văn hoặc bất kỳ thứ gì trả về thứ hạng mà bạn có thể sắp xếp theo. Tôi không chắc chắn làm thế nào họ sẽ được trọng lượng chống lại eachother, nhưng tôi chắc chắn bạn có thể tinker một lúc và con số nó ra. Ví dụ:

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

Tôi không nghĩ câu trả lời được chấp nhận sẽ giải quyết được sự cố. Nếu bạn cố gắng tìm tất cả các sách từ một tác giả nào đó và, do đó, hãy sử dụng tên tác giả (hoặc một phần của nó) làm tiêu chí tìm kiếm, những sách duy nhất được truy vấn trả về sẽ là những sách có tiêu chí tìm kiếm theo tên riêng của nó . Cách duy nhất tôi thấy xung quanh vấn đề này là sao chép các cột của Tác giả mà bạn muốn tìm kiếm trong bảng Sách và lập chỉ mục các cột đó (hoặc cột vì nó có thể thông minh để lưu trữ thông tin liên quan của tác giả trong một XML). trong bảng Sách).

1

FWIW, trong tình huống tương tự, DBA của chúng tôi đã tạo trình kích hoạt DML để duy trì bảng tìm kiếm toàn văn chuyên dụng. Nó không thể sử dụng một cái nhìn vật chất vì nhiều hạn chế của nó.

3

tôi đã có vấn đề tương tự như bạn nhưng nó thực sự tham gia vào 10 bảng (một bảng Users và một số người khác để biết thông tin)

Tôi đã truy vấn đầu tiên của tôi sử dụng FREETEXT trong mệnh đề WHERE cho mỗi bảng nhưng truy vấn đã được tham gia quá dài.

Sau đó tôi thấy một số câu trả lời về việc sử dụng FREETEXTTABLE thay thế và kiểm tra giá trị không rỗng trong cột khóa cho mỗi bảng, nhưng cũng mất nhiều thời gian để thực thi.

tôi cố định nó bằng cách sử dụng một sự kết hợp của FREETEXTTABLE và UNION chọn:

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 

này được chứng minh là vô cùng nhanh hơn nhiều.

Tôi hy vọng điều đó sẽ hữu ích.

0

Câu trả lời này là quá hạn, nhưng một cách để thực hiện việc này nếu bạn không thể sửa đổi bảng chính là tạo bảng mới có tham số tìm kiếm được thêm vào một cột.

Sau đó, tạo chỉ mục văn bản đầy đủ trên cột đó và truy vấn cột đó.

Ví dụ

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 

Trong đoạn mã trên [EAN]. [Dbo]. [TblEanFullTextSearch], FullTextSearchColumn là bảng mới và cột với các lĩnh vực nói thêm, bây giờ bạn có thể làm một truy vấn trên bảng mới với các tham gia vào bảng bạn muốn hiển thị dữ liệu từ đó.

Hy vọng điều này sẽ giúp

Các vấn đề liên quan