Добро пожаловать в форум, Guest >> Войти | Регистрация | Поиск | Правила | | В избранное | Подписаться | ||
Все форумы / Microsoft SQL Server |
![]() ![]() |
DeviLooper Member Откуда: Сообщений: 41 |
Суть такая. Есть таблица data в ней помимо прочего 4 текстовых поля с полнотекстовым индексом. Нужно реализовать поиск по всем 4-м полям (для каждого поля своя строка поиска), объединяя эти условия по "И" или по "ИЛИ" На выходе нужно получить 1 таблицу с полями [key] и [rank] Плюс еще нужно отсеивать записи по другим полям таблицы data (например, по root_id) Для "И" (т.е. когда должны совпасть все 4 строки) додумался до такого: select s1.[key],s1.rank+s2.rank+s3.rank+s4.rank as rank from data, containstable(data,[name],'"text1*"') as s1 inner join containstable(data,[text],'"text2*"') as s2 on s2.[key] = s1.[key] inner join containstable(data,[actors],'"text3*"') as s3 on s3.[key] = s2.[key] inner join containstable(data,[author],'"text4*"') as s4 on s4.[key] = s3.[key] where data.root_id = 1 and data.id = s1.[key]; Вроде бы все работает, как задумывал. Что-то оптимизировать/доработать тут можно? А вот по "ИЛИ" (когда совпадает хотя бы 1 строка) не могу сообразить как лучше сделать. Думал с помощью UNION: select s.[key],s.[rank] from data, ( select * from containstable(data,[name],'"text1*"') as s1 union select * from containstable(data,[text],'"text2*"') as s2 union select * from containstable(data,[actors],'"text3*"') as s3 union select * from containstable(data,[author],'"text4*"') as s4 ) as s where data.root_id = 1 and data.id = s.[key]; Тоже вроде как работает, но в результирующей таблице могут быть дублирующиеся строки с одинаковым [key] (если сработало несколько containstable для одной и той же строки из data) Т.е. по идее нужно еще в результирующей таблице объединить все дубликаты по [key] с вычислением их суммарного [rank]. Как бы это сделать? |
22 авг 15, 15:00 [18054580] Ответить | Цитировать Сообщить модератору |
churupaha Member Откуда: Краснодар Сообщений: 1015 |
DeviLooper, во внутреннем подзапросе select [key], sum(rank) as rank from ( /* портянка union'ов */ ) group by [key] |
22 авг 15, 15:29 [18054618] Ответить | Цитировать Сообщить модератору |
churupaha Member Откуда: Краснодар Сообщений: 1015 |
+ union, заменить на union all, потому, как containstable возвращает и колонку rank, а он различный будет для строк с одним и тем же [key] в общем случае. из плана уйдет "distinct фаза" для объединения. |
22 авг 15, 15:33 [18054625] Ответить | Цитировать Сообщить модератору |
DeviLooper Member Откуда: Сообщений: 41 |
churupaha, Во, спасибо! То, что надо! А так, в целом, нормальный запрос или что-то улучшить можно? |
22 авг 15, 15:41 [18054636] Ответить | Цитировать Сообщить модератору |
churupaha Member Откуда: Краснодар Сообщений: 1015 |
запрос, как запрос. может и можно улучшить, но сегодня шаббат. |
||
22 авг 15, 15:42 [18054638] Ответить | Цитировать Сообщить модератору |
DeviLooper Member Откуда: Сообщений: 41 |
churupaha, Понятно, все равно спасибо. ;) |
22 авг 15, 15:44 [18054640] Ответить | Цитировать Сообщить модератору |
DeviLooper Member Откуда: Сообщений: 41 |
Может, кому пригодится, вот итоговый запрос по "ИЛИ" data.id - primary key select [key],sum([rank]) as [rank] from data, ( select * from containstable(data,[name],'"test1*"') union all select * from containstable(data,[text],'"test2*"') union all select * from containstable(data,[actors],'"test3*"') union all select * from containstable(data,[author],'"test4*"') ) as s where id=s.[key] and root_id=1 group by s.[key]; если отсеивание по дополнительным полям не нужно, то, соответственно, убираем where и "data," из from |
22 авг 15, 18:12 [18054908] Ответить | Цитировать Сообщить модератору |
Все форумы / Microsoft SQL Server | ![]() |