views:

68

answers:

1

I have a table which contains my ads that can be searched in sql-server-2008. See the following piece of code. is_searchable in the ad_search table is basically the flag for whether this ad should be included in the search.

The three examples below produce unreasonable output in my mind:

In the first example 1000 records are returned. all with is_searchable set to 0. These rows are useless to me in this use case.

The second example shows the result of having a where clause filtering out is_searchable records that are not true. Because none were returned in the containstable in the from part of the query none were returned when the where clause was applied.

The third example only has the top_n_by_rank changed from 1000 to 4000.

So my question is how can I just get the TOP 1000 or n results with my "is_searchable =1" clause?

use live;

declare @search_text as varchar(2000) = '"*interlet*"'


--- TOP 1000 without clause (returns 1000 rows (all with is_searchable = 0)
select is_searchable, *
from CONTAINSTABLE (ad_search, searchText, @search_text, 1000) AS KEY_TBL
inner join ad_search (nolock) ON ad_search.ad_search_id = KEY_TBL.[KEY]
inner join ad_search_view_data on ad_search_view_data.ad_search_id = ad_search.ad_search_id


--- TOP 1000 with "where ad_search.is_searchable = 1" clause returns 0 rows
select is_searchable, *
from CONTAINSTABLE (ad_search, searchText, @search_text, 1000) AS KEY_TBL
inner join ad_search (nolock) ON ad_search.ad_search_id = KEY_TBL.[KEY]
inner join ad_search_view_data on ad_search_view_data.ad_search_id = ad_search.ad_search_id
where ad_search.is_searchable = 1

-- TOP 4000 
select is_searchable, *
from CONTAINSTABLE (ad_search, searchText, @search_text, 4000) AS KEY_TBL
inner join ad_search (nolock) ON ad_search.ad_search_id = KEY_TBL.[KEY]
inner join ad_search_view_data on ad_search_view_data.ad_search_id = ad_search.ad_search_id
where ad_search.is_searchable = 1 
+1  A: 

Try this:

DECLARE @N int
SET @N=325

SELECT TOP(@N)
    is_searchable, *
    from CONTAINSTABLE (ad_search, searchText, @search_text) AS KEY_TBL
    inner join ad_search (nolock) ON ad_search.ad_search_id = KEY_TBL.[KEY]
    inner join ad_search_view_data on ad_search_view_data.ad_search_id = ad_search.ad_search_id
    where ad_search.is_searchable = 1
    ORDER BY KEY_TBL.Rank DESC

@N can be 1000 or whatever you want it to be

KM
Do you think this will drastically reduce performance? I had read that the top_n_by_rank parameter is important in keeping the performance requirements moderate within a CONTAINSTABLE()
Stewart Robinson
@Stewart Robinson, I'm sure it will slow it down. You make no mention of the performance of the current table or any row counts, so I have no way of telling. This query will return what you want, but may be slow. the problem you are running into is that your CONTAINSTABLE returns the best N rows, you then filter those, which causes you to miss data. My query has CONTAINSTABLE rank everything then you filter, and miss nothing. This is slower, but returns what you want. With your given query, can't you just use LIKE?
KM
Another possible solution is to use my query above but create a View: `SELECT * FROM ad_search WHERE is_searchable = 1`, and use it in place of `ad_search`, which is permitted within CONTAINSTABLE as per the doc: *table Is the name of a table that has been full-text indexed. table can be a one-, two-, three-, or four-part database object name. When querying a view, only one full-text indexed base table can be involved.* http://msdn.microsoft.com/en-us/library/ms189760.aspx
KM

related questions