May 31, 2006 at 7:27 am
You mentioned you had duplicates using the first FreeTextTable. UNION eliminates dupes, so I'm not sure what you mean.
1. To combine the result sets and eliminate duplicate rows (that is, two rows that match column for column), combine the queries with UNION.
2. To combine the results sets without eliminating duplicate rows, use UNION ALL.
Result sets combined with UNION or UNION ALL must consist of the same number of columns with matching data types
----------------------------------------------------------------------
There are many ways to accomplish multiple search criteria. One way is to search for rows where the keyword is present in both Author AND Title at the same time, INNER JOIN two CONTAINSTABLE() result sets.
-- Example
DECLARE @KW varchar(100)
SET @KW = '"sql server"'
SELECT FT_TBL.Title
, FT_TBL.[First Name - 1]
, FT_TBL.[Last Name - 1]
, KEY1.RANK AS RankAuthor
, KEY2.RANK AS RankTitle
FROM tbl_books AS FT_TBL
JOIN CONTAINSTABLE (tbl_books, author, @KW) AS KEY1
ON FT_TBL.ID = KEY1.
JOIN CONTAINSTABLE (tbl_books, title, @KW) AS KEY2
ON FT_TBL.ID = KEY2.
ORDER BY CASE
WHEN KEY1.RANK >= KEY2.RANK THEN KEY1.RANK
ELSE KEY2.RANK
END
DESC
May 31, 2006 at 10:48 am
That works perfectly. However, for the ordering by rank, I have created a new column called Rank = RankAuthor + RankTitle and then it works even better. Ok, so for using AND, I use JOIN, for OR if I am not mistaken LEFT OUTER JOIN, but what can I use for NOT? Example: Author but NOT title. Also, I have fixed the author Query, now it works pretty well. The one last problem I am having is that there is no match within those separate joins, the rankX is just an empty field. Therefore when I add all the Ranks together to form the final rank, if there was any empty rank, the final rank is going to be empty too. Is there are ny how to specify at the begining that the Rank would be equal to 0 or something? I am so happy, almost done with this.
SELECT FT_TBL.Title,
FT_TBL.[Last Name - 1], FT_TBL.[First Name - 1], FT_TBL.[Series],
KEY1.RANK AS RANK1, KEY2.RANK AS RANK2, KEY3.RANK AS RANK3,
KEY4.RANK AS RANK4,
(KEY1.RANK + KEY2.RANK + KEY2.RANK + KEY3.RANK) AS RANK
FROM tbl_books AS FT_TBL " +
JOIN FreeTextTable(tbl_books, [Last Name - 1], @KW) AS KEY1
ON FT_TBL.ID = KEY1.[Key]
LEFT OUTER JOIN FreeTextTable(tbl_books, [First Name - 1], @KW) AS KEY2
ON FT_TBL.ID = KEY2.[Key]
LEFT OUTER JOIN FreeTextTable(tbl_books, [Last Name - 2], @KW) AS KEY3
ON FT_TBL.ID = KEY3.[Key]
LEFT OUTER JOIN FreeTextTable(tbl_books, [First Name - 2], @KW) AS KEY4
ON FT_TBL.ID = KEY4.[Key]
ORDER BY RANK DESC
May 31, 2006 at 11:17 am
I solved the rank counting problem, I have used the COALESCE() function for assigning a value to a field in case that it is null. so the line which was previously:
(KEY1.RANK + KEY2.RANK + KEY2.RANK + KEY3.RANK) AS RANK
is now:
(COALESCE(KEY1.RANK,0) + COALESCE(KEY2.RANK,0) + COALESCE(KEY2.RANK,0) + COALESCE(KEY3.RANK,0)) AS RANK
If anybody knows about nicer solution, I would love to know it, as this one does not look too nice...but it works
May 31, 2006 at 11:34 am
It appears you're finally getting close to your solution. Regarding the question about NOT ( your example: Author but NOT title ), since the NOT column (title in this case) will not return any rank info, why not use
WHERE NOT Contains(title, ----)
May 31, 2006 at 11:59 am
That seems fairly easy, I will give it a try. I guess there si no easy solution for using NOT SOME_OPERATION containstable(title, ...). And for ordering, if I am correct, I have to do the joins first and then do the NOT part? And in case I have multiple NOT search fields, can I use WHERE NOT (Contains(title, ...) or Contains(author,...))?
May 31, 2006 at 12:09 pm
JOIN is part of the FROM clause. That is followed by the WHERE clause, which can have multiple NOT Contains(). Whether you connected them with OR or with AND would depend on the particular query.
May 31, 2006 at 4:01 pm
So when I though that I am finally getting all the SQL right, I ran into another problem. I am trying to search for author OR title, while using the FULL OUTER JOIN. However, when I handle the author first and then title, all the fields of the table which came from the title query are empty, except for the RANK. When I do it the other way(title OR author), everything works perfectly. I have no clue what is wrong and I need this, because I am generating the queries in a script and no hand generating them. Here are the queries:
Author OR Title:
"SELECT FT_TBL.Title
, FT_TBL.[Series]
,FT_TBL.[First Name - 1]
, FT_TBL.[Last Name - 1]
, KEY1.RANK AS RANK1
,(COALESCE(KEY1.RANK,0) + COALESCE(KEY1_A1.RANK,0) + COALESCE(KEY2_A1.RANK,0) + COALESCE(KEY3_A1.RANK,0) + COALESCE(KEY4_A1.RANK,0) + COALESCE(KEY5_A1.RANK,0) + COALESCE(KEY6_A1.RANK,0)) AS RANK
FROM tbl_books AS FT_TBL
JOIN
FreeTextTable(tbl_books, [Last Name - 1], 'jamieson OR sewall OR dock OR suhrie') AS KEY1_A1 ON FT_TBL.ID = KEY1_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [First Name - 1], 'jamieson OR sewall OR dock OR suhrie') AS KEY2_A1 ON FT_TBL.ID = KEY2_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [Last Name - 2], 'jamieson OR sewall OR dock OR suhrie') AS KEY3_A1 ON FT_TBL.ID = KEY3_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [First Name - 2], 'jamieson OR sewall OR dock OR suhrie') AS KEY4_A1 ON FT_TBL.ID = KEY4_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [Last Name- 3], 'jamieson OR sewall OR dock OR suhrie') AS KEY5_A1 ON FT_TBL.ID = KEY5_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [First Name - 3], 'jamieson OR sewall OR dock OR suhrie') AS KEY6_A1 ON FT_TBL.ID = KEY6_A1.[Key]
FULL OUTER JOIN
FREETEXTTABLE (tbl_books, Title,'Nursing education in the South') AS KEY1 ON FT_TBL.ID = KEY1."
Title and Author:
"SELECT FT_TBL.Title
, FT_TBL.[Series]
,FT_TBL.[First Name - 1]
, FT_TBL.[Last Name - 1]
, KEY1.RANK AS RANK1
,(COALESCE(KEY1.RANK,0) + COALESCE(KEY1_A1.RANK,0) + COALESCE(KEY2_A1.RANK,0) + COALESCE(KEY3_A1.RANK,0) + COALESCE(KEY4_A1.RANK,0) + COALESCE(KEY5_A1.RANK,0) + COALESCE(KEY6_A1.RANK,0)) AS RANK
FROM tbl_books AS FT_TBL
JOIN
FREETEXTTABLE (tbl_books, Title,'Nursing education in the South') AS KEY1 ON FT_TBL.ID = KEY1.
FULL OUTER JOIN
FreeTextTable(tbl_books, [Last Name - 1], 'jamieson OR sewall OR dock OR suhrie') AS KEY1_A1 ON FT_TBL.ID = KEY1_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [First Name - 1], 'jamieson OR sewall OR dock OR suhrie') AS KEY2_A1 ON FT_TBL.ID = KEY2_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [Last Name - 2], 'jamieson OR sewall OR dock OR suhrie') AS KEY3_A1 ON FT_TBL.ID = KEY3_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [First Name - 2], 'jamieson OR sewall OR dock OR suhrie') AS KEY4_A1 ON FT_TBL.ID = KEY4_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [Last Name- 3], 'jamieson OR sewall OR dock OR suhrie') AS KEY5_A1 ON FT_TBL.ID = KEY5_A1.[Key] LEFT OUTER JOIN
FreeTextTable(tbl_books, [First Name - 3], 'jamieson OR sewall OR dock OR suhrie') AS KEY6_A1 ON FT_TBL.ID = KEY6_A1.[Key] "
June 1, 2006 at 6:34 am
@words varchar(1000), @wordcount int, @i int
@sql varchar(8000), @sql2 varchar(8000), @sql3 varchar(8000)
@word table(id int identity, word varchar(40))
@expr table(rank int, wordid int, expr varchar(8000),length as len(expr))
@words = 'rim,steel,aluminium,wheel,strong,spokes'
@sql = 'select ''"' + replace(replace(@words, char(39), char(39)+char(39)),',','"'' union all select ''"') + '"'''
@word(word) exec(@sql)
@expr(rank, wordid, expr) select 1, id, word from @word
@wordcount = @@rowcount, @i = 2
@i <= @wordcount
insert @expr(rank,wordid, expr)
select @i, w.id, e.expr + ' NEAR ' + w.word
@STR varchar(8000)
@STR = 'ISABOUT('
@STR = @STR + expr + ' weight('+str(1.000/((@wordcount-rank)+1.0),3,1)+ '),
@expr
expr is not null
@STR = substring(@STR,1,len(@STR)-3) + ')'
CT.RANK,p.description
Production.ProductDescription p
containstable(
.ProductDescription
Description
as CT
CT. = p.ProductDescriptionID
by CT.RANK desc
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
June 1, 2006 at 8:06 am
Your second query
is (in relevant respects) of the form:
1
tbl_books B
(select ID from tbl_books where col1 = 1) B1 on B1.ID = B.ID
outer join (select ID from tbl_books where col1 = 2) B2 on B2.ID = B1.ID
join (select ID from tbl_books where col1 = 3) B3 on B3.ID = B2.ID
join (select ID from tbl_books where col1 = 4) B4 on B4.ID = B3.ID
join (select ID from tbl_books where col1 = 5) B5 on B5.ID = B4.ID
join (select ID from tbl_books where col1 = 6) B6 on B6.ID = B5.ID
join (select ID from tbl_books where col1 = 7) B7 ON B7.ID = B6.ID
1
tbl_books B
join (select ID from tbl_books where col1 = 1) B1 on B1.ID = B.ID
join (select ID from tbl_books where col1 = 2) B2 on B2.ID = B1.ID
join (select ID from tbl_books where col1 = 3) B3 on B3.ID = B2.ID
join (select ID from tbl_books where col1 = 4) B4 on B4.ID = B3.ID
join (select ID from tbl_books where col1 = 5) B5 on B5.ID = B4.ID
join (select ID from tbl_books where col1 = 6) B6 on B6.ID = B5.ID
join (select ID from tbl_books where col1 = 7) B7 ON B7.ID = B6.ID
(B2.ID is not null
, it would probably be preferable if you didn't need to have 7 'keys' tables
, FREETEXTTABLE, CONTAINS, or CONTAINSTABLE statement.
use CONTAINSTABLE - since the FREETEXT variants don't allow NEAR and WEIGHT,
Tim Wilkinson
"If it doesn't work in practice, you're using the wrong theory"
- Immanuel Kant
June 2, 2006 at 12:35 pm
Finally after all troubles I got it work! The search is pretty good, I know that my query is probably violating all the rules, but unfortunately, I cannot influence the table design. I was able to get all the logic working(AND, OR, NOT) so I am very happy right now. Thank you all for your help!
Viewing 10 posts - 16 through 24 (of 24 total)
You must be logged in to reply to this topic. Login to reply