2008-11-21 43 views
6

Hiện tại tôi có một bảng mà tôi tìm kiếm trên 4 trường, FirstName, LastName, MiddleName và AKA's. Tôi hiện đang có một tìm kiếm CONTAINSTABLE cho các hàng và nó hoạt động. Không tốt nhưng nó hoạt động. Bây giờ Tôi muốn đặt tên cho tên họ và tên đệm có trọng số thấp hơn.Tìm kiếm văn bản đầy đủ của máy chủ SQL có trọng số

Tôi tìm thấy lệnh ISABOUT nhưng điều đó có vẻ khá vô giá trị nếu tôi phải thực hiện bằng từ không cột (hy vọng tôi hiểu điều này sai). Đây không phải là một lựa chọn nếu nó từng chữ bởi vì tôi không biết có bao nhiêu từ mà người dùng sẽ nhập vào.

Tôi tìm thấy chủ đề here nói về cùng một giải pháp này tuy nhiên tôi không thể nhận giải pháp được chấp nhận để hoạt động. Có lẽ tôi đã làm điều gì đó sai trái nhưng bất kể tôi không thể làm cho nó hoạt động được, và logic của nó có vẻ thực sự ... kỳ quặc. Cần phải có một cách dễ dàng hơn.

Trả lời

6

Chìa khóa để thao tác bảng xếp hạng là sử dụng liên minh. Đối với mỗi cột, bạn sử dụng một câu lệnh chọn riêng. Trong tuyên bố đó, thêm một số nhận dạng cho thấy từ đó mỗi cột được kéo sau đó. Chèn kết quả vào một biến bảng, sau đó bạn có thể thao tác xếp hạng bằng cách sắp xếp trên số nhận dạng hoặc nhân thứ hạng theo một số giá trị dựa trên số nhận dạng.

Điều quan trọng là cung cấp cho sự xuất hiện của việc sửa đổi thứ hạng, không thực sự thay đổi xếp hạng của máy chủ sql.

Ví dụ sử dụng một biến bảng:

DECLARE @Results TABLE (PersonId Int, Rank Int, Source Int) 

Đối với bảng Người Cột PersonId Int PK Identity, FirstName VarChar(100), MiddleName VarChar(100), LastName VarChar(100), AlsoKnown VarChar(100) với mỗi cột thêm vào một danh mục văn bản đầy đủ, bạn có thể sử dụng các truy vấn:

INSERT INTO @Results (PersonId, Rank, Source) 

SELECT PersonId, Rank, 1 
FROM ContainsTable(People, FirstName, @SearchValue) CT INNER JOIN People P ON CT.Key = P.PersonId 

UNION 
SELECT PersonId, Rank, 2 
FROM ContainsTable(People, MiddleName, @SearchValue) CT INNER JOIN People P ON CT.Key = P.PersonId 

UNION 
SELECT PersonId, Rank, 3 
FROM ContainsTable(People, LastName, @SearchValue) CT INNER JOIN People P ON CT.Key = P.PersonId 

UNION 
SELECT PersonId, Rank, 4 
FROM ContainsTable(People, AlsoKnown, @SearchValue) CT INNER JOIN People P ON CT.Key = P.PersonId 

/* 
Now that the results from above are in the @Results table, you can manipulate the 
rankings in one of several ways, the simplest is to pull the results ordered first by Source then by Rank. Of course you would probably join to the People table to pull the name fields. 
*/ 

SELECT PersonId 
FROM @Results 
ORDER BY Source, Rank DESC 

/* 
A more complex manipulation would use a statement to multiply the ranking by a value above 1 (to increase rank) or less than 1 (to lower rank), then return results based on the new rank. This provides more fine tuning, since I could make first name 10% higher and middle name 15% lower and leave last name and also known the original value. 
*/ 

SELECT PersonId, CASE Source WHEN 1 THEN Rank * 1.1 WHEN 2 THEN Rank * .9 ELSE Rank END AS NewRank FROM @Results 
ORDER BY NewRank DESC 

Một nhược điểm là bạn sẽ nhận thấy tôi đã không sử dụng UNION ALL, vì vậy nếu một từ xuất hiện trong nhiều cột, thứ hạng sẽ không phản ánh điều đó. Nếu đó là một vấn đề bạn có thể sử dụng UNION ALL và sau đó loại bỏ id người trùng lặp bằng cách thêm tất cả hoặc một phần của thứ hạng bản ghi trùng lặp vào thứ hạng của một bản ghi khác với cùng một id người.

+0

Điều này cực kỳ hữu ích! Đó là một sự xấu hổ rằng điều này không được xây dựng trong SQL Server rồi. –

+0

tuy nhiên điều này không tóm tắt thứ hạng .... – yeeen

2

Các cấp bậc là vô ích trên các chỉ mục, bạn không thể hợp nhất chúng và mong đợi kết quả có ý nghĩa gì đó. Số thứ tự của mỗi chỉ mục là các so sánh táo/cam/nho/dưa hấu/cặp không có tương đối có nghĩa là nội dung WRT của các chỉ mục khác. Chắc chắn bạn có thể thử và liên kết/trọng số/thứ tự xếp hạng giữa các chỉ mục để thử và fudge một kết quả có ý nghĩa nhưng vào cuối ngày kết quả vẫn còn vô nghĩa tuy nhiên có thể vẫn đủ tốt để cung cấp một giải pháp khả thi tùy thuộc vào chi tiết cụ thể. Quay lại đầu trang của tình hình của bạn.

Theo quan điểm của tôi, giải pháp tốt nhất là đặt tất cả dữ liệu bạn có thể tìm kiếm trong một chỉ mục/cột FTS duy nhất và sử dụng các cột đó để xếp hạng đầu ra của bạn .. Ngay cả khi bạn phải sao chép nội dung trường để thực hiện kết quả .

0

Tôi cho rằng dữ liệu được trả lại được nối với các bảng khác trong lược đồ của bạn? Tôi sẽ phát triển RANK của riêng bạn dựa trên các cột từ dữ liệu liên quan đến chỉ mục văn bản đầy đủ. Điều này cũng cung cấp mức độ chính xác được đảm bảo trong giá trị RANK.

2

Chỉ vài tuần trước, tôi đã giải quyết được vấn đề và giải pháp rất giống nhau là đáng ngạc nhiên dễ dàng (mặc dù tiêu thụ không tốt và không gian). Tạo một cột khác chứa các giá trị kết hợp là FirstName + FirstName + LastName + MiddleName theo thứ tự này.Cột FirstName trùng lặp là không phải là lỗi đánh máy, đó là một mẹo để buộc FT vào giá trị trọng số từ FirstName cao hơn trong khi tìm kiếm.

0

Làm thế nào về cách này:

SELECT p.* from Person p 
left join ContainsTable(Person, FirstName, @SearchValue) firstnamefilter on firstnamefiler.key = p.id 
left join ContainsTable(Person, MiddleName, @SearchValue) middlenamefilter on middlenamefilter.key = p.id 
where (firstnamefilter.rank is not null or middlenamefilter.rank is not null) 
order by firstnamefilter.rank desc, middlenamefilter.rank desc 

này sẽ tạo ra một kỷ lục cho mỗi bản ghi Person nơi một trong hai tên đầu tiên hoặc giữa (hoặc cả hai) trận đấu trên cụm từ tìm kiếm và trật tự của tất cả các trận đấu chống lại người đầu tiên tên đầu tiên (theo thứ tự xếp hạng giảm dần), tiếp theo là tất cả các kết quả trùng khớp với tên đệm (một lần nữa theo thứ tự xếp hạng giảm dần)

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