Мне нужно ранжировать эти строки:
Именно таким образом:
Без типа Cat это обычная RANK() функция SQL.
«Кошка» в рейтинге не должна отнимать позиции у других собак. Тип «Кошка» должен иметь тот же ранг, что и следующий тип «Собака», независимо от очков.
Функциональность RANK() необходима для всех типов «собак» (в примере Бадди и Дюк — 4-е, а Макс — 6-е).
Возможно создание временной таблицы/хранимой процедуры и дальнейшая обработка результатов... но я хотел бы знать, есть ли более простой способ сделать это.
Временная таблица вам точно не понадобится. Если вы предоставляете DDL+DML, вам будет намного проще помогать людям.
@DaleK Вы правы, но я использовал только функцию RANK()... У меня заканчиваются идеи XD


Отрегулируйте оценку кошки так, чтобы она соответствовала следующей оценке собаки, а затем ранжируйте ее. (Или плотный ранг... желаемые результаты в нынешнем виде тоже не совпадают).
WITH cte AS (
SELECT
Type,
Name,
Score,
MAX(CASE WHEN Type = 'Dog' THEN Score END) OVER (ORDER BY Score ASC) NewScore
FROM YourTable
)
SELECT Type, Name, Score,
DENSE_RANK() OVER (ORDER BY NewScore DESC) DenseRank,
RANK() OVER (ORDER BY NewScore DESC) Rank
FROM cte
ORDER BY Score DESC;
Возврат:
О, я, возможно, неправильно понял... исходя из желаемых результатов, возможно, вы хотите сначала ранжировать собак, а затем просто присоединиться к кошкам... в этом случае это то, что вам нужно.
WITH cte AS (
SELECT
Type,
Name,
Score,
CASE WHEN Type = 'Dog' THEN RANK() OVER (PARTITION BY CASE WHEN Type = 'Dog' THEN 1 END ORDER BY Score DESC) END DogRank
FROM YourTable
)
SELECT Type, Name, Score,
MIN(DogRank) OVER (ORDER BY Score ASC) Rank
FROM cte
ORDER BY Score DESC;
Возврат:
Это разумно использовать MAX, чтобы объединить их вместе!
Возможным решением является сочетание:
RANK() с соответствующим разделом (чтобы ранжировать только те строки, где Type находится Dog) и правильным предложением ORDER BY.LEAD() с IGNORE NULLS (введено в SQL Server 2022).Обратите внимание: если вы хотите получить рейтинг без пробелов в значениях рейтинга, вы можете использовать DENSE_RANK() вместо RANK().
Пример данных испытаний:
SELECT *
INTO Data
FROM (VALUES
('Dog', 'Teddy', 50),
('Cat', 'Mary', 1),
('Cat', 'Ana', 70),
('Dog', 'Max', 10),
('Dog', 'Rocky', 70),
('Cat', 'Zoe', 45),
('Cat', 'Nelly', 40),
('Dog', 'Buddy', 20),
('Dog', 'Daisy', 30),
('Dog', 'Duke', 20)
) v (Type, Name, Score)
Т-SQL:
SELECT
Type, Name, Score, DogRank,
Rank = COALESCE(
DogRank,
LEAD(DogRank) IGNORE NULLS OVER (ORDER BY Score DESC, DogRank),
COUNT(*) OVER ()
-- or MAX(DogRank) OVER () + 1
)
FROM (
SELECT
*,
DogRank = CASE WHEN Type = 'Dog' THEN RANK() OVER (PARTITION BY CASE WHEN Type = 'Dog' THEN 1 END ORDER BY Score DESC) END
FROM Data
) t
ORDER BY Score DESC, DogRank
Результат:
С этим есть две проблемы... 1) Если у Зои 70 (как у Рокки), ее ранг равен 2, но он должен быть 1. 2) если у Зои 1, ее ранг равен «нулевому», а не 8.
@Сэмюэль, тебе нужно добавить все крайние случаи в образец данных. И вы объясняете, что если бы Зое было 1, то ранг был бы 8? И на самом деле, как Зоя 70 должна иметь ранг 1, а не 2, как вы сказали, кошка никогда не должна превосходить собаку по рангу.
@Сэмюэль, решение для первого краевого случая (... если у Зои 70 баллов...) - это другое предложение ORDER BY в функции LEAD(), но я не уверен, почему вам нужен ранг 8 (вместо 7) ), если у Зои 1 балл. Ответ обновляется с использованием дополнительных тестовых данных.
Будет здорово увидеть, что вы попробовали.