Я бы использовал подзапрос, чтобы получить значения функции в результате, а затем функцию ранжирования ROW_NUMBER, например:
select
ROW_NUMBER() over (order by t.cnt desc) as RowId, t.*
from
(
SELECT
h.A, hrl.B, dbo.f_GetCount(hrl.A,h.B) as cnt
FROM
dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE
(@A IS NULL OR h.A like '%' + @A + '%') AND
(@B IS NULL OR hrl.B = @B)
GROUP BY
hrl.B, h.A
) as t
order by
1
Если вам нужен только определенный раздел результатов (скажем, для разбивки на страницы), вам потребуется другой подзапрос, а затем выполнить фильтрацию по номеру строки:
select
t.*
from
(
select
ROW_NUMBER() over (order by t.cnt desc) as RowId, t.*
from
(
SELECT
h.A, hrl.B, dbo.f_GetCount(hrl.A,h.B) as cnt
FROM
dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE
(@A IS NULL OR h.A like '%' + @A + '%') AND
(@B IS NULL OR hrl.B = @B)
GROUP BY
hrl.B, h.A
) as t
) as t
where
t.RowId between 1 and 10
order by
t.RowId
Обратите внимание, что в этом запросе вы можете поместить ROW_NUMBER в любое место списка выбора, поскольку вы больше не полагаетесь на использование синтаксиса "order by 1" для оператора order by.
Здесь возникает небольшая проблема при многократном вызове этого запроса. Не гарантируется, что порядок, в котором возвращаются записи, будет согласованным, если количество элементов в каждой группе не уникально. Чтобы решить эту проблему, вы должны изменить функцию ROW_NUMBER на порядок полей, которые составляют группу в подсчете.
В этом случае это будут A и B, в результате чего:
select
t.*
from
(
select
ROW_NUMBER() over (order by t.cnt desc, t.A, t.B) as RowId, t.*
from
(
SELECT
h.A, hrl.B, dbo.f_GetCount(hrl.A,h.B) as cnt
FROM
dbo.hrl
INNER JOIN dbo.h on h.C = hrl.C
WHERE
(@A IS NULL OR h.A like '%' + @A + '%') AND
(@B IS NULL OR hrl.B = @B)
GROUP BY
hrl.B, h.A
) as t
) as t
where
t.RowId between 1 and 10
order by
t.RowId
Это приводит к последовательному упорядочению результатов между вызовами, когда количество элементов между группами не уникально (при условии, что один и тот же набор данных).