Пользовательские функции ранжирования/аналитики в SQL Server 2008

StackOverflow https://stackoverflow.com/questions/1740026

Вопрос

Я планирую миграцию хранилища данных на SQL Server 2008 и пытаюсь придумать способы репликации аналитических функций LAG, LEAD, FIRST_VALUE и LAST_VALUE из Oracle в SQL Server 2008.Они не включены в SQL Server 2008, хотя основной механизм оконных аналитических функций (например,ROW_NUMBER, RANK и DENSE_RANK присутствуют).

Для этих функций можно добиться той же функции, создав подзапрос, который присваивает каждой строке номер с помощью ROW_NUMBER, а затем выполняя самообъединения этого запроса для поиска связанных строк с соседними номерами строк (для LAG и LEAD) или номер строки 1 (для FIRST_VALUE).

Я ожидаю, что выполнение самосоединений снизит эффективность операции:но у меня пока нет SQL-сервера, чтобы проверить это.Поэтому, не оценив производительность, мне интересно, есть ли лучший обходной путь, позволяющий избежать самообъединений.

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

Итак, мой вопрос:Можете ли вы добавить предложение OVER() после пользовательской агрегатной функции, чтобы она вызывалась как аналитическая функция?

Если да, то вызывается ли метод Terminate() один раз для каждой строки?Требуется ли что-то особенное, чтобы гарантировать отправку строк в вашу UDF в порядке, указанном в предложении OVER()?

Это было полезно?

Решение

Я бы использовал самообъединения, а не udfs.

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

Кроме того, функции Oracle не являются агрегатными функциями.Пользовательский агрегат все равно должен будет выполнять ту же обработку над набором результатов.

Помните, что внутри Oracle все равно придется выполнять некоторую построчную обработку, чтобы вычислить значения.

Итак, пример SQL Server 2005+ для FIRST_VALUE (не проверялось) с использованием самостоятельного соединения.

Обратите внимание на перекрестное соединение, которое отделяет FIRST_VALUE от остальных 2, поскольку наборы результатов не имеют никакой связи.Если вы использовали UDF или определяемое пользователем agg, то, скорее всего, вам придется вычислять FIRST_VALUE снова и снова для каждой строки из первого набора результатов.

;WITH CTE AS
(
    SELECT
        department_id, last_name, salary,
        ROW_NUMBER() OVER (ORDER BY salary) AS ranking
    FROM employees
    WHERE department_id = 90
)
SELECT
    c1.department_id, c1.last_name, c1.salary,
    c2.last_name as Poorest
FROM
    CTE c1
    CROSS JOIN
    (SELECT last_name FROM CTE WHERE Ranking = 1) c2
ORDER BY
    c1.employee_id

Другие советы

В SQL-сервере аналитика является частью SSAS;там вы найдете FirstNonEmpty, LastNonEmpty, FirstChild, LastChild.Он включен в стандартную и корпоративную версии SQL-сервера; глянь сюда.То есть, если вы хотите строить кубики.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top