Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MS SQL Server > Подбор условия выборки в зависимости от параметра


Автор: mihryak 6.4.2012, 15:28
Привет!

Пытаюсь написать табличную фукцию для полнотекстового поиска, выбирающую предикат FREETEXT или CONTAINS в зависимости от переданного параметра.

Код

    declare    @searchKey    nvarchar(200)
    declare    @exactMatch    bit
    
    set @searchKey = 'help desk';
    set @exactMatch = 0;

    --set @searchKey = '"help" AND "desk"';
    --set @exactMatch = 1;

    with CategoryCTE as
    (
        select
            RootCategory.Id
        from
            Category RootCategory            
        where
            (@exactMatch = 0 and freetext(RootCategory.Title, @searchKey)) or
            (@exactMatch = 1 and contains(RootCategory.Title, @searchKey))
        
        union all
        
        select
            ChildCategory.Id
        from
            Category ChildCategory
                inner join
                    CategoryCTE ccte on ChildCategory.ParentId = ccte.Id    
    )
    
    select * from CategoryCTE


Судя по ошибке про неправильный синтаксис запроса при выполении мой функции (CONTAINS не поддерживает несколько слов; их надо через OR или AND перечислять), оба условия выполняются полностью, что недопустимо.

http://dba.stackexchange.com/questions/5333/logical-operators-or-and-in-condition-and-order-of-conditions-in-where, что нельзя полагаться на порядок и полноту вычисления предикатов.

Через CASE переписать условие тоже не вышло, так что пока что единственным получившимся у меня вариантом является создание ещё одной такой же функции (в них, кажется, нельзя писать IF), только с CONTAINS вместо FREETEXT. А в хранимке, которая их вызывает, уже проврять параметр и решать, какую вызвать. Это отвратительно и грустно.

Нет ли идей, что можно тут сделать, чтобы избежать массированной копипасты? Это только кусок реального запроса, который в жизни куда больше, что ещё больше вызывает нежелание копипастить. В скуле мало что смыслю, так что рад буду любому совету.


Автор: Zloxa 9.4.2012, 09:19
Цитата(mihryak @  6.4.2012,  16:28 Найти цитируемый пост)
Это отвратительно и грустно.

Не грустите. Это нормально. Для разных предикатов доступа таки много лучше использовать разные запросы. Повторное использование, это совсем не про SQL. Здесь это скорее зло. Ибо вью на вью на вью на вью = смерть.

Если я правильно понял суть проблемы, вы можете:
1) Использовать временную таблицу, в которую будете сохранять результаты отбора по freeText или по contains двумя запросами, в завиимости от параметра, и в своем мегаэпическом запросе, в качестве источника, использовать эту временную таблицу

2) Вместо оператора or использовать union all. Правда не уверен я в том, как это задружит с рекурсивным cte, но, полагаю, правильная расстановка скобок позволит им замириться

3) Вас никто не заставляет использовать один и тот же паттерн для free text и contains. Вы можете использовать разные, которые будете вычислять в зависимости от параметра (читобы синтаксис не ругался)

Автор: mihryak 9.4.2012, 11:12
Zloxa, спасибо!
Мне и правда надо научиться перестраиваться с императивных языков на скуль

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)