Я внедряю поисковый механизм на веб-сайте и наткнулся на его аспект SQL.
Пользователь может искать истории по любой комбинации этих фильтров: заголовок истории, тег истории или имя пользователя автора истории. Если фильтр не предусмотрен, просто верните все истории.
Мое непосредственное решение этой проблемы - хранимая процедура:
(
@TitleFilter varchar(50) = NULL
,@TagFilter varchar(30) = NULL
,@UserFilter varchar(30) = NULL
)
SELECT
story.Title
,story.AddedDTS
FROM
Stories story
INNER JOIN FREETEXTTABLE(Stories, Title, @TitleFilter) ft
ON ft.[key] = story.ID
LEFT JOIN StoryTags st
ON st.StoryID = story.ID
LEFT JOIN Tags tag
ON tag.ID = st.TagID
LEFT JOIN StoryUser su
ON su.StoryID = story.ID
LEFT JOIN Users u
ON u.ID = su.UserID
WHERE
1=1
AND (
(@TagFilter IS NULL AND @UserFilter IS NULL)
OR (@TagFilter IS NOT NULL AND tag.Name = @TagFilter)
OR (@UserFilter IS NOT NULL AND u.Username = @UserFilter)
)
Однако есть несколько проблем с этим, и мне еще предстоит найти лучший подход.
Прежде всего, в таблице Stories
включен полнотекстовый поиск, поэтому я должен использовать механизм FREETEXTTABLE
, который предписывает предикату не быть NULL
, поэтому эта хранимая процедура не будет работать с @TitleFilter
установлен на NULL
.
Во-вторых, если я выполняю поиск только по названию, то объединение с таблицами StoryTags
, Tags
, StoryUsers
и Users
- это просто бесполезные накладные расходы.
Итак, вопрос к обоим пунктам, которые я указал: могу ли я условно опустить соединения, чтобы оптимизировать время выполнения?
Если к этому есть совершенно другой подход, вы можете поделиться им; Я выступаю за нестандартное мышление.