SQL Rank не работает должным образом

Я пытаюсь использовать функцию SQL Rank(), чтобы получить список лучших записей нескольких групп. Вот что я делаю, что не работает:

select hc.hId, hc.DpId, hc.Rank 
from (
    select d.hId, DpId, Rank()
        OVER (Partition by DpId ORDER BY d.hId) AS Rank
    FROM CurDp d
    INNER JOIN HostList h on d.DpId = h.hId
    INNER JOIN Coll_hList pch on d.hId = pch.hId
    where h.Model = 'PRIMARY'  
) hc where hc.Rank <= 10

Я получаю 10 лучших записей следующим образом:

 HId    | DpId | Rank
 -------x------x------
  7     | 590  | 1
  18    | 590  | 2
  23    | 590  | 3
  24    | 590  | 4
  26    | 590  | 5
  36    | 590  | 6
  63    | 590  | 7
  80    | 590  | 8
  84    | 590  | 9
  88    | 590  | 10

Но когда я использую CROSS APPLY, функция, которая мне нужна, потому что мне нужно получать такие записи на разных моделях, я использую этот код:

select pch.hId, cc.DpId, cc.Rank from from Coll_hList pch
cross apply
(
    select hc.hId, hc.DpId, hc.Rank 
    from (
        select d.hId, DpId, Rank()
            OVER (Partition by DpId ORDER BY d.hId) AS Rank
        FROM CurrDp d
        INNER JOIN HostList h on d.DpId = h.hId
        where h.Model = 'PRIMARY' and d.hId = pch.hId
    ) hc where hc.Rank <= 10
) cc

Здесь я всегда получаю ранг 1, и он ничего не фильтрует (не показывает весь результат):

HId    | DpId | Rank
-------x------x------
7        590    1
18       590    1
23       590    1
24       590    1
26       590    1
36       590    1
63       590    1
80       590    1
84       590    1
88       590    1
124      590    1
125      590    1
133      590    1

Я делаю это неправильно? Это из-за CROSS APPLY?

Я также использовал плотное_rank() вместо rank(), но оно показывает тот же результат.

Мы будем очень признательны за любую помощь в выполнении этого запроса с помощью CROSS APPLY.

Спасибо


person Aeron    schedule 12.10.2015    source источник


Ответы (1)


В первом случае вы присоединяетесь к Coll_hList и получаете набор результатов из более чем 10 записей, которые затем ранжируются.

Во втором случае в вашем apply-sub-select вы создаете только набор результатов с одной записью. Ранжирование этого приводит к первому рангу.

Ваше ранжирование должно быть выполнено во внешнем выражении:

select pch.hId, cc.DpId, Rank()
            OVER (Partition by cc.DpId ORDER BY cc.hId) AS Rank 
from  Coll_hList pch
cross apply
(
        select d.hId, DpId
        FROM CurrDp d
        INNER JOIN HostList h on d.DpId = h.hId
        where h.Model = 'PRIMARY' and d.hId = pch.hId

) cc
person flo    schedule 12.10.2015
comment
Привет, спасибо за ваш ответ, это прекрасно работает. Я просто не понял ваш набор результатов с одной записью. Вы имеете в виду, что метод ранжирования видит только один результат, который нельзя отсортировать? - person Aeron; 12.10.2015
comment
Точно. Синтаксис перекрестного применения создает своего рода временную таблицу для каждой строки набора результатов, вычисленного ранее выполненными соединениями (по крайней мере, это помогает думать об этом таким образом), которая затем объединяется только с этой конкретной строкой. В вашем случае временные таблицы имеют только одну строку. - person flo; 12.10.2015