i have never use PATINDEX() but i hard the table data can be search with PATINDEX().
often i got requirement to search multiple column of any table then i write the sql like
SELECT * FROM ADDRESS WHERE
((NAME LIKE 'Bill%') OR (CITY LIKE 'Bill%') OR (COMPANY LIKE 'Bill%'))
AND
((NAME LIKE 'Seattle%') OR (CITY LIKE 'Seattle%') OR (COMPANY LIKE 'Seattle%'))
so just tell me the above my sql performance will be good always? i search google to get better sql for searching multiple column of a table and found the below sql
select * from YourTable
WHERE PATINDEX('%text1%',COALESCE(field1,'') + '|' + COALESCE(field2,'') + '|'+ COALESCE(field3,'')+ '|' + COALESCE(field4,'')+ '|' + COALESCE(field9,''))>0
AND
PATINDEX('%text2%',COALESCE(field1,'') + '|' + COALESCE(field2,'') + '|'+ COALESCE(field3,'')+ '|' + COALESCE(field4,'')+ '|' +COALESCE(field9,''))>0
please guide me that the above sql PATINDEX syntax is ok for searching multiple column. if not then guide me how can i use the PATINDEX function to search multiple column with multiple value. thanks
UPDATE QS
you gave a link and that show me how to search multiple fields with multiple keyword. here it is
SELECT FT_TBL.ProductDescriptionID,
FT_TBL.Description,
KEY_TBL.RANK
FROM Production.ProductDescription AS FT_TBL INNER JOIN
CONTAINSTABLE (Production.ProductDescription,
Description,
'(light NEAR aluminum) OR
(lightweight NEAR aluminum)'
) AS KEY_TBL
ON FT_TBL.ProductDescriptionID = KEY_TBL.[KEY]
WHERE KEY_TBL.RANK > 2
ORDER BY KEY_TBL.RANK DESC;
GO
but the problem is it is bit complicated to understand. can u give me sql for searching multiple fields with multiple keywords with full text search.
can i write something like this for searching multiple fields against multiple value
SELECT Title
FROM Production.Document
WHERE FREETEXT (Document, '(vital) OR (safety) OR (components)')
SELECT *
FROM YourTable
WHERE CONTAINS((ProductName, ProductNumber, Color),
'(vital) OR (safety) OR (components)');
what is the difference between FREETEXT and CONTAINS ?? can u please explain.
thanks
for fast search multiple columns you can setup Full-Text Search on sql server
then your queries will look like that
SELECT * FROM ADDRESS
WHERE Contains((name, city, company), 'Bill') and Contains(*, 'Seattle')
EDIT
Syntax of full-text search queries described here
EDIT
you can write
SELECT *
FROM YourTable
WHERE CONTAINS((ProductName, ProductNumber, Color),
'"vital" OR "safety" OR "components"');
rows that contains any of words in any searched column are returned. check this answer
for difference between contains and freetext check Sql Server Full-Text Search Protips Part 2: CONTAINS vs. FREETEXT article
Related
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
I am using full text searching on a SQL Server database to return results from multiple tables. The simplest situation would be searching a persons name fields and a description field. The code I use to do this looks like:
select t.ProjectID as ProjectID, sum(t.rnk) as weightRank
from
(
select KEY_TBL.RANK * 1.0 as rnk, FT_TBL.ProjectID as ProjectID
FROM Projects as FT_TBL
INNER JOIN FREETEXTTABLE(Projects, Description, #SearchText) AS KEY_TBL
ON FT_TBL.ProjectID=KEY_TBL.[KEY]
union all
select KEY_TBL.RANK * 50 as rnk, FT_TBL.ProjectID as ProjectID
FROM Projects as FT_TBL
... <-- complex unimportant join
INNER JOIN People as p on pp.PersonID = p.PersonID
INNER JOIN FREETEXTTABLE(People, (FirstName, LastName), #SearchText) AS KEY_TBL
ON p.PersonID=KEY_TBL.[KEY]
)
group by ProjectID
As is (hopefully) clear above, I am trying to weight heavily on matches of a person's name over matches in a project description field. If I do a search for something like 'john' all projects with a person named john on it will be heavily weighted (as expected). The issue I am having is on searches where someone provides a full name like 'john smith'. In this case the match is much less strong on name as (I presume) only half the search terms are matching in each of the firstname / lastname columns. In many cases this means someone with an exact match of the name entered will not necessarily be returned near the top of the search results.
I have been able to correct this by searching each of the firstname / lastname fields separately and adding their scores together so my new query looks like:
select t.ProjectID as ProjectID, sum(t.rnk) as weightRank
from
(
select KEY_TBL.RANK * 1.0 as rnk, FT_TBL.ProjectID as ProjectID
FROM Projects as FT_TBL
INNER JOIN FREETEXTTABLE(Projects, Description, #SearchText) AS KEY_TBL
ON FT_TBL.ProjectID=KEY_TBL.[KEY]
union all
select KEY_TBL.RANK * 50 as rnk, FT_TBL.ProjectID as ProjectID
FROM Projects as FT_TBL
... <-- complex unimportant join
INNER JOIN People as p on pp.PersonID = p.PersonID
INNER JOIN FREETEXTTABLE(People, (FirstName), #SearchText) AS KEY_TBL
ON p.PersonID=KEY_TBL.[KEY]
union all
select KEY_TBL.RANK * 50 as rnk, FT_TBL.ProjectID as ProjectID
FROM Projects as FT_TBL
... <-- complex unimportant join
INNER JOIN People as p on pp.PersonID = p.PersonID
INNER JOIN FREETEXTTABLE(People, (LastName), #SearchText) AS KEY_TBL
ON p.PersonID=KEY_TBL.[KEY]
)
group by ProjectID
My question:
Is this the approach I should be taking, or is there some way to have the full text searching operate on a list of columns as though it were a blob of text: i.e. treat the firstname and lastname columns as a single name column, resulting in a higher scoring match for strings including both the persons first and last name?
I have recently run into this and have used a computed column to concatenate the required columns together into one string and then have the full text index on that column.
I have achieved the weighting by duplicating the weighted fields in the computed column.
i.e. last name appears 3 times and first name once.
ALTER TABLE dbo.person ADD
PrimarySearchColumn AS
COALESCE(NULLIF(forename,'') + ' ' + forename + ' ', '') +
COALESCE(NULLIF(surname,'') + ' ' + surname + ' ' + surname + ' ', '') PERSISTED
You must make sure you use the persisted keyword so that the column isnt computed on each read.
I know this is an old question but I've come across the same issue and solved it a different way.
Rather than add computed columns to the original tables, which may not always be an option, I have created indexed views which contain the combined fields. To use the original example:
CREATE VIEW [dbo].[v_PeopleFullName]
WITH SCHEMABINDING
AS SELECT dbo.People.PersonID, ISNULL(dbo.People.FirstName + ' ', '') + dbo.People.LastName AS FullName
FROM dbo.People
GO
CREATE UNIQUE CLUSTERED INDEX UQ_v_PeopleFullName
ON dbo.[v_PeopleFullName] ([PersonID])
GO
Then I join that view in my query, along with the existing full-text predicate on the individual columns in the base table, so that I can find exact matches and partial matches in the individual columns, like so:
DECLARE #SearchText NVARCHAR(100) = ' "' + #OriginalSearchText + '" ' --For matching exact phrase
DECLARE #SearchTextWords NVARCHAR(100) = ' "' + REPLACE(#OriginalSearchText, ' ', '" OR "') + '" ' --For matching on words in phrase
SELECT FT_TBL.ProjectID as ProjectID,
ISNULL(KEY_TBL.[Rank], 0) + ISNULL(KEY_VIEW.[Rank], 0) AS [Rank]
FROM Projects as FT_TBL
INNER JOIN People as p on FT_TBL.PersonID = p.PersonID
LEFT OUTER JOIN CONTAINSTABLE(People, (FirstName, LastName), #SearchTextWords) AS KEY_TBL ON p.PersonID = KEY_TBL.[KEY] INNER JOIN
LEFT OUTER JOIN CONTAINSTABLE(v_PeopleFullName, FullName, #SearchText) AS KEY_VIEW ON p.PersonID = KEY_VIEW.[Key]
WHERE ISNULL(KEY_TBL.[Rank], 0) + ISNULL(KEY_VIEW.[Rank], 0) > 0
ORDER BY [Rank] DESC
Some notes on this:
I'm using CONTAINSTABLE rather than FREETEXTTABLE as it seems more appropriate to me for searching names. I'm not interested in finding words with similar meaning or inflections of words when it's names that I'm searching on.
Because I'm using CONTAINSTABLE I'm having to do some pre-processing on the #SearchText variable to make it compatible and to break it down into individual words with the OR operator for searching on the base table's full-text index.
Rather than using a UNION query to join separate queries each using a single, joined CONTAINSTABLE I'm joining on both CONTAINSTABLE predicates in the same query. This means using outer joins rather than inner joins, so I'm then using a WHERE clause to exclude any records from the base table which don't match on either full-text index. I confess that I haven't made any examination of how this performs compared to separate queries each with a single full-text index predicate UNIONised to produce a single result set.
Although there's no guarantee that the Rank of matches on the full search text in the indexed view will be higher than that of matches on individual words in the full-text index on the base table's columns because the Rank value is arbitrary, my testing so far has shown that in practice it always is (so far!).
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%'
Can anyone tell me how to query a fulltext table in Sql Server, and get only exactly matches? Example:
I have those records in a table named "Items":
Bath
Bathroom
Test
Testing
I need to query for Bath and get only 1 record, "bath", excluding the word Bathroom. The same to the word "Test", wich in my context is different to "Testing".
Have you tried
SELECT column1, column2, ...
FROM [itens] AS FT_TBL INNER JOIN
CONTAINSTABLE([itens], *, 'Bath') AS KEY_TBL
ON FT_TBL.unique_key_column = KEY_TBL.[KEY]
http://msdn.microsoft.com/en-us/library/ms189760.aspx
or
SELECT columnname
FROM [itens]
WHERE CONTAINS(somecolumn, 'Bath')
http://msdn.microsoft.com/en-us/library/ms187787.aspx
Just noticed the updated questions (formatting applied).
If you column holds keywords (single word) then you could just select column = 'keyword'.
SELECT columnname
FROM [itens]
WHERE somecolumn = 'Bath'
are you searching for bath and test in one query or in different?
if in single, then one of the solutions i see is:
select top 1 from table where column like '[., ]bath[., ]%'
if in different, then union a series of such select's
I'm trying to work out a SQL Select in MS SQL 2005, to do the following:
TABLE_A contains a list of keywords... asparagus, beetroot, beans, egg plant etc (x200).
TABLE_B contains a record with some long free text (approx 4000 chars)...
I know what record within TABLE_B I am selecting (byID).
However I need to get a shortlist of records from TABLE_A that are contained WITHIN the text of the record in TABLE_B.
I'm wondering if SQLs CONTAINS function is uselful... but maybe not.
This needs to be a super quick query.
Cheers
It will never be super quick because of the LIKE and wildcard at each end. You can not index it and there are no whizzy tricks. However, because you have already filtered TableB then it should be acceptable. If you had a million rows in tableB, you could go for coffee while it ran
SELECT
A.KeyWordColumn
FROM
TableA A
JOIN
TableB B ON B.BigTextColumn LIKE '%' + A.KeyWordColumn+ '%'
WHERE
B.ByID = #ID --or constant etc
CONTAINS can be used if you have full text indexing: but not for a normal SQL query
I would try this
select keyword from table_a, table_b
where table_b.text like '%' + keyword + '%'
and table_b.Id = '111'