SQL Server Full-Text-Index Search does not work - sql-server

The full-text-index searches are not returning the expected results. The index is built by now, but not finding some really basic strings.
This query does not return the user called "Other 11".
SELECT KEY_TBL.RANK, FT_TBL.Firstname
FROM [user].[User] AS FT_TBL
INNER JOIN
CONTAINSTABLE([user].[User], Firstname,
'"Other*"') AS KEY_TBL
ON FT_TBL.UserId = KEY_TBL.[KEY]
ORDER BY KEY_TBL.RANK DESC
GO
If I rewrite the query like this, it will work and return the user called "Other 11".
SELECT KEY_TBL.RANK, FT_TBL.Firstname
FROM [user].[User] AS FT_TBL
INNER JOIN
CONTAINSTABLE([user].[User], Firstname,
'"Other 11"') AS KEY_TBL
ON FT_TBL.UserId = KEY_TBL.[KEY]
ORDER BY KEY_TBL.RANK DESC
GO
Something similar happens with FREETEXTTABLE and CONTAINS with a predicate search is also not working.
What could be the reason for this behavior?

Other and 11 are two differents words.
With a FTS predicate like '"Other*"' you will find "Otherwise" but never "Other 11"
You need to use a NEAR predicate like :
'NEAR((Other, 11),1, TRUE)'

Related

SQL Server FTS indexing correct keywords but not returning results with those keywords

I've created a FTS catalog which indexes the Title column of a table called Articles. The word breaker language is set to Dutch.
The article title is "Contactgegevens Wijkteams 2019". My search term is 'contactgegevens' which is Dutch for 'Contact details'. This word could potentially be split into 'contact' and 'gegevens', although I have checked the indexed keywords which has successfully indexed the full word from the correct table/column.
Search term:
declare #searchTerm nvarchar(100)
select #searchTerm = 'contactgegevens';
Using Freetext:
If I use FREETEXT in the where clause I do find the result but it comes up near the end of around 300 rows. The majority of the rows don't have this word in the title column, not even words close in meaning.
SELECT a.ArticleID, a.Title
FROM Articles a
WHERE
FREETEXT(a.Title, #searchTerm))
Using FreeTextTable:
With FREETEXTTABLE, I get far less results but not one of them contain the keyword:'contactgegevens' or variations of it.
select *
from
freetexttable(Articles, Title, #search, LANGUAGE N'Dutch', 100) as key_table
inner join
Articles a on a.ArticleID = key_table.[Key]
order by
key_table.RANK desc
Using ContainsTable:
CONTAINSTABLE seems to return very similar results to FREETEXTTABLE.
SELECT key_table.rank, a.*
FROM Articles a
INNER JOIN
CONTAINSTABLE(Articles, Title, #searchTerm, LANGUAGE N'Dutch', 100) AS key_table on key_table.[KEY] = a.ArticleID
WHERE
ORDER BY
key_table.rank DESC
As mentioned I've checked the indexed keywords using the following query:
select *
from sys.dm_fts_index_keywords(DB_ID('MyDatabase'), OBJECT_ID('Articles'))
where (display_term like 'contactgegevens%') and column_id = 3
order by display_term
and the keyword is indexed for the correct table/column and looking at records close to this result I can see it's indexed other words relevant to the article title I'm looking for.
I'm expecting to be able to do a search for a phrase such as "Contactgegevens Wijkteams 2019" and have the article with that exact title appear at the top of the list, but it doesn't. In some cases it doesn't appear in the search results at all.
What am I missing here?
Turns out it was a simple mistake on my part. My join was using the ArticleID instead of the ArticleVersionID which is what the Catalog uses as its unique key and what is represented by key_table.[KEY].
SELECT key_table.rank, a.*
FROM Articles a
INNER JOIN
CONTAINSTABLE(Articles, Title, #searchTerm, LANGUAGE N'Dutch', 100) AS key_table on key_table.[KEY] = a.ArticleVersionID
WHERE
ORDER BY
key_table.rank DESC

sql count query over a count query

following is my query to get the count of documentid
select count(did),did
from (
select count(FileDataId) as fid,
documentid as did,
FileDataId
from DocumentHistory
where documentid in (
select documentid
from Document
where DocumentTypeId=11 and
IsVerified=0 and
lastmodified < '5/jan/2019'
)
group by DocumentId,
filedataid
having count(FileDataId)<2
)
I am getting error as
Incorrect syntax near ')'.
If i run the inner query, it is bringing me result
I like to know how many times the did is repeating in the result
I guess it's because you haven't put an alias for your subquery. You're also missing a grouping in the outer query. The formatting of your query could be improved too:
select
count(a.did),
a.did
from (
select
count(dh.FileDataId) as fid,
dh.documentid as did,
dh.FileDataId
from DocumentHistory dh
INNER JOIN Document d on d.documentid = dh.documentid
where d.DocumentTypeId=11 and d.IsVerified=0 and d.lastmodified < '2019-01-05'
group by DocumentId, filedataid
having count(FileDataId)<2
) a
GROUP BY did
As well as incorporating simon's suggestion
surrounding the date format (yyyy-mm-dd is ISO, and not subject to localisation problems like a date that contains words- your query might not work on eg a Spanish database), I swapped the IN for an INNER JOIN too; though query optimizers can generally rewrite IN to behave like a join you should aim to avoid using IN for lists longer than you'd be prepared to write by hand. Some databases are better optimised for join than in
Note, having said that, that there's a slight difference in behaviour between an INNER JOIN and IN, if the IN(...) list contains duplicates you won't get repeated rows out of documenthistory result but you would with an inner join. (I expect that documentid is a primary key of document so duplicates wouldn't appear in this case)

SQL SERVER - FETCH NEXT ROWS returns duplicate results

I had a very weird issue in my website, and finally I succeeded to pinpoint the exact cause.
In my 'Entities' table I have several columns, such as "Id", "Title", "Date", "Indexing" and some more.
"Indexing" column indexed with full-text index.
Consider the following SQL query:
SELECT Id
FROM [dbo].[Entities] AS DocTable
INNER JOIN CONTAINSTABLE(Entities, Indexing, 'otherCriteria OR criteia') AS KEY_TBL
ON DocTable.Id = KEY_TBL.[KEY]
ORDER BY KEY_TBL.RANK DESC
This query works as expected and I getting around 600 results.
Now I adding pagination:
SELECT Id
FROM [dbo].[Entities] AS DocTable
INNER JOIN CONTAINSTABLE(Entities, Indexing, 'otherCriteria OR criteia') AS KEY_TBL
ON DocTable.Id = KEY_TBL.[KEY]
ORDER BY KEY_TBL.RANK DESC
OFFSET 50 ROWS FETCH NEXT 10 ROWS ONLY
No matter if I using OFFSET 30 or 40 or 50 -> I always getting exactly the same results!
Now the really weird part: if inside SELECT I asking to select 'Title' also (e.g. SELECT Id, Title) --> I getting correct results.
Any ideas?
OK, I think I got it
In Sql Server 2014 ORDER BY clause with OFFSET FETCH NEXT returns weird results
Says:
The ORDER BY clause contains a column or combination of columns that
are guaranteed to be unique.
Obviously, "RANK" is not unique. When I changed my query to:
SELECT Id
FROM [dbo].[Entities] AS DocTable
INNER JOIN CONTAINSTABLE(Entities, Indexing, 'otherCriteria OR criteia') AS KEY_TBL
ON DocTable.Id = KEY_TBL.[KEY]
ORDER BY KEY_TBL.RANK DESC, Id
OFFSET 50 ROWS FETCH NEXT 10 ROWS ONLY
I received correct results

Filtering Query with NOT EXISTS

I am currently attempting to query a database using SQL Server in Visual Studio. The database in question contains payment information, primarily identifying transactions and their resulting software licenses via OrderID and License ID. Ocassionally, these licenses get revoked due to misuse.
Right now, I'm attempting to run a query that returns all customers based upon this:
Select
[Order].LastName,
[Order].FirstName,
[Order].CompanyOrganization,
[Order].EmailAddress,
[Order].Country,
[License].LicenseID,
[License].InstanceCount
From [Order], [License]
Where
[License].OrderID = [Order].OrderID
AND [Order].Status = 1
AND not exists (Select LicenseID From [LicenseRevocation])
Order by [License].InstanceCount DESC;
The query returns no results, and I know it's because of the "NOT EXISTS" portion. However, I'm not sure why. Can somebody clear up how "EXISTS" works and how to implement it into my query?
The exists() function is true if the query inside it would produce at least one record, thus not exists() is only true if the query inside it would produce zero records.
In your case you are querying the entire LicenseRevocation inside not exists(), so your query would only return anything if that table was completely empty.
You would use a condition in the query to look for a specific record in it, something like this:
not exists (Select * From [LicenseRevocation] Where LicenseID = [License].LicenceID)
That will make the query return the records where there is no corresponding record in the LicenseRevocation table.
You need to define a condition on which you check for values if there exist or not,
Also use ON clause syntax for your joins.
Select [Order].LastName
, [Order].FirstName
, [Order].CompanyOrganization
, [Order].EmailAddress
, [Order].Country
, [License].LicenseID
, [License].InstanceCount
From [Order]
INNER JOIN [License] ON [License].OrderID = [Order].OrderID
Where [Order].[Status] = 1
AND NOT EXISTS (Select 1
From [LicenseRevocation]
WHERE LicenseID = [License].LicenseID) --<-- you are missing this condition
Order by [License].InstanceCount DESC;
this solution uses NOT IN and proper JOIN syntax but should give you the result you want
SELECT [Order].LastName, [Order].FirstName, [Order].CompanyOrganization,
[Order].EmailAddress, [Order].Country,
[License].LicenseID, [License].InstanceCount
FROM [Order]
INNER JOIN [License] ON [License].OrderID = [Order].OrderID
WHERE [Order].Status = 1
AND [License].LicenseID NOT IN (
SELECT LicenseID
FROM [LicenseRevocation] )
ORDER BY [License].InstanceCount DESC;
ps. use table ALIAS
First of all, write your query using proper JOINS, and use a standard LEFT OUTER JOIN:
Select
[Order].LastName,
[Order].FirstName,
[Order].CompanyOrganization,
[Order].EmailAddress,
[Order].Country,
[License].LicenseID,
[License].InstanceCount
From [Order]
INNER JOIN [License] ON [License].OrderID = [Order].OrderID
LEFT OUTER JOIN [LicenseRevocation] ON [License].LicenseID = [LicenseRevocation].LicenseID
Where [Order].Status = 1
AND [LicenseRevocation].LicenseID IS NULL
Order by [License].InstanceCount DESC;

FreetextTable Query

I have written an sql query to search 2 columns of a database, partNo and Description and it works fine for searching descriptions however if you search for a part number such as 164 it picks up all of the part numbers which start with 164 such as say: 164-20 but it doesn't pickup results like say APS164-20
here is my sql code, I am running mssql 2005.
SELECT FT_TBL.*, KEY_TBL.RANK
FROM Parts AS FT_TBL
INNER JOIN FREETEXTTABLE(Parts,(PartNo, Description),
'164') AS KEY_TBL
ON FT_TBL.PartNo = KEY_TBL.[KEY]
ORDER BY KEY_TBL.RANK DESC;
GO
I tried containstable but that didn't return the rows either
Full text search won't cover this scenario, where you're essentially looking for the search term as a substring within the text.
Try a traditional wildcard search instead:
SELECT *
FROM Parts AS FT_TBL
WHERE FT_TBL.PartNo like '%164%'

Resources