Сортировка столбца по различным параметрам сортировки в SQL Server - PullRequest
5 голосов
/ 11 октября 2010

У меня есть таблица Companies с многоязычным столбцом CompanyName (определенным как nvarchar (512)).

У меня также есть хранимая процедура для поиска и возврата списка компаний, она принимает 2 параметра nvarchar -один - это поисковый термин, а другой - код языка ISO.

Я хотел бы иметь возможность возвращать результаты поиска, отсортированные с сопоставлением, соответствующим коду языка, указанному во втором.параметр, например:

SELECT * FROM dbo.Companies WHERE CompanyName LIKE '%searchstring%'
ORDER BY
    CASE @lang
        WHEN 'sv' THEN CompanyName COLLATE Sami_Sweden_Finland_100_CI_AI
        WHEN 'ch' THEN CompanyName COLLATE Chinese_Simplified_Pinyin_100_CI_AI
                ELSE CompanyName
    END

, однако я получаю следующую ошибку при попытке его запустить:

Не удается разрешить конфликт параметров сортировки между "Chinese_Simplified_Pinyin_100_CI_AI" и "Sami_Sweden_Finland_100_CI_AI" воперация CASE.

Это не имеет смысла для меня - это не то, что я сортирую по параметрам сортировки, почему может возникнуть конфликт параметров сортировки?Это взаимоисключающий выбор.

Я пытался не быть слишком умным и просто использовать динамический sql, к сожалению, это, похоже, оставляет базу данных неспособной кешировать план выполнения, поэтому время запроса занимает более 20секунд (в отличие от 1), когда таблица содержит около 2 миллионов строк.

Я уверен, что сортировка с учетом культурных особенностей должна быть распространенной проблемой, кто-нибудь знает хорошее решение, которое не включает изменениетекущая схема (например, как необходимость создания дополнительных столбцов)?

Ответы [ 2 ]

2 голосов
/ 11 октября 2010

Хорошо, я наконец-то нашел ответ на этот вопрос, благодаря @gbn, ваше решение определенно было правильным, учитывая мое первоначальное определение вопроса.

Однако оказывается, что я работал в ошибочном предположении, что следует избегать динамического SQL. Чтобы это работало, мне пришлось добавить вычисляемый (и проиндексированный) столбец со значением

CompanyName COLLATE [Collation_Name]

для каждого сопоставления, которое мне нужно было отсортировать (я понимаю, что в своем исходном вопросе я сказал, что не хочу изменять схему, но на самом деле я имел в виду, что не хочу перемещать существующие данные).

При выполнении следующего запроса

EXEC('SELECT TOP 10 * FROM dbo.Companies
      WHERE CompanyName LIKE ''%searchstring%''
      ORDER BY CompanyName COLLATE ' + @collation)

механизм запросов выбирает индекс для соответствующего вычисляемого столбца, и я получаю быстрый ответ. К сожалению, при использовании запроса, предоставленного @gbn, индексы, созданные для вычисляемых столбцов, игнорируются, что приводит к снижению производительности.

Это все очень удивляет меня, так как я всегда считал, что динамический SQL - это зло, которого следует избегать, если в этом нет крайней необходимости (т. Е. Когда ваш запрос изменяется так, что вы не можете параметризовать)

2 голосов
/ 11 октября 2010

Acolumn может иметь только одно сопоставление. Дело о том, что вы пытаетесь иметь несколько, которые конфликтуют друг с другом. Попробуйте это:

SELECT * FROM dbo.Companies WHERE CompanyName LIKE '%searchstring%'
ORDER BY
    CASE @lang
        WHEN 'sv' THEN CompanyName ELSE '' END 
    END COLLATE Sami_Sweden_Finland_100_CI_AI,
    CASE @lang
        WHEN 'ch' THEN CompanyName ELSE '' END 
    END Chinese_Simplified_Pinyin_100_CI_AI
...