Один из вариантов - использовать переменную ранжирования, например:
SELECT first_name,
age,
gender,
@curRank := @curRank + 1 AS rank
FROM person p, (SELECT @curRank := 0) r
ORDER BY age;
Эта (SELECT @curRank := 0)
часть позволяет инициализировать переменную без отдельной SET
команды.
Прецедент:
CREATE TABLE person (id int, first_name varchar(20), age int, gender char(1));
INSERT INTO person VALUES (1, 'Bob', 25, 'M');
INSERT INTO person VALUES (2, 'Jane', 20, 'F');
INSERT INTO person VALUES (3, 'Jack', 30, 'M');
INSERT INTO person VALUES (4, 'Bill', 32, 'M');
INSERT INTO person VALUES (5, 'Nick', 22, 'M');
INSERT INTO person VALUES (6, 'Kathy', 18, 'F');
INSERT INTO person VALUES (7, 'Steve', 36, 'M');
INSERT INTO person VALUES (8, 'Anne', 25, 'F');
Результат:
+------------+------+--------+------+
| first_name | age | gender | rank |
+------------+------+--------+------+
| Kathy | 18 | F | 1 |
| Jane | 20 | F | 2 |
| Nick | 22 | M | 3 |
| Bob | 25 | M | 4 |
| Anne | 25 | F | 5 |
| Jack | 30 | M | 6 |
| Bill | 32 | M | 7 |
| Steve | 36 | M | 8 |
+------------+------+--------+------+
8 rows in set (0.02 sec)
partition by gender
часть аналитической функции (которая «нумерует» значение ранга для пола, а не для общего результата)Вот общее решение, которое присваивает строки плотный ранг над разделением. Он использует пользовательские переменные:
Обратите внимание, что назначения переменных помещаются внутри
CASE
выражения. Это (в теории) заботится о порядке оценки вопроса.IS NOT NULL
Добавляются для обработки типа данных преобразования и короткие вопросы замыкания.PS: Он может быть легко преобразован в номер строки в разделе путем удаления всех условий, которые проверяют связь.
Демо на дб <> скрипка
источник
ELSE @rank_count := @rank_count + 1
ORDER BY gender, age DESC
?В то время как ответ с наибольшим количеством голосов занимает место, он не разбивается на разделы, вы можете выполнить самостоятельное присоединение, чтобы разделить все это также:
Случай использования
Ответ :
источник
Доработка версии Даниила для расчета процентиля и ранга. Также два человека с одинаковыми оценками получат одинаковое звание.
Результаты запроса для образца данных -
источник
Сочетание ответа Дэниела и Салмана. Однако звание не дадут, поскольку продолжается последовательность с галстуками. Вместо этого он пропускает звание до следующего. Таким образом, максимум всегда достигает количества строк.
Схема и контрольный пример:
Вывод:
источник
Начиная с MySQL 8, вы, наконец, можете использовать оконные функции также в MySQL: https://dev.mysql.com/doc/refman/8.0/en/window-functions.html
Ваш запрос может быть написан точно так же:
источник
@Sam, ваша точка зрения превосходна в концепции, но я думаю, что вы неправильно поняли, что документы MySQL говорят на указанной странице - или я неправильно понял :-) - и я просто хотел добавить это, чтобы, если кто-то чувствует себя некомфортно с @ Ответ Даниэля, они будут более уверены или, по крайней мере, будут копать глубже.
Вы видите, что
"@curRank := @curRank + 1 AS rank"
внутриSELECT
это не «одно утверждение», это одна «атомарная» часть утверждения, поэтому оно должно быть безопасным.В документе, на который вы ссылаетесь, приводятся примеры, где одна и та же пользовательская переменная в 2 (атомарных) частях оператора, например,
"SELECT @curRank, @curRank := @curRank + 1 AS rank"
,.Кто-то может возразить, что
@curRank
в ответе @ Daniel дважды используется: (1)"@curRank := @curRank + 1 AS rank"
и (2) the,"(SELECT @curRank := 0) r"
но поскольку второе использование является частьюFROM
предложения, я уверен, что оно гарантированно будет оценено первым; по сути, сделав это вторым и предшествующим заявлением.Фактически, на той же самой странице документации MySQL, на которую вы ссылались, вы увидите то же решение в комментариях - это может быть то, откуда @Daniel получил его; да, я знаю, что это комментарии, но это комментарии на официальной странице документации, и это имеет некоторый вес.
источник
Наиболее простым решением для определения ранга данного значения является подсчет количества значений перед ним. Предположим, у нас есть следующие значения:
30
значения считаются третьими40
значения считаются 6-м (ранг) или 4-м (плотный ранг)Теперь вернемся к первоначальному вопросу. Вот некоторые примеры данных, которые отсортированы, как описано в OP (ожидаемые ранги добавляются справа):
Чтобы рассчитать
RANK() OVER (PARTITION BY Gender ORDER BY Age)
для Сары , вы можете использовать этот запрос:Для расчета
RANK() OVER (PARTITION BY Gender ORDER BY Age)
для всех строк вы можете использовать этот запрос:И вот результат (добавленные значения добавляются справа):
источник
Если вы хотите оценить только одного человека, вы можете сделать следующее:
Это ранжирование соответствует функции оракула RANK (где, если у вас есть люди одного возраста, они получают одинаковый ранг, а ранжирование после этого непоследовательное).
Это немного быстрее, чем использовать одно из приведенных выше решений в подзапросе и выбрать из него, чтобы получить рейтинг одного человека.
Это может быть использовано для ранжирования всех, но это медленнее, чем приведенные выше решения.
источник
Person
таблице растет. Это O (n ^ 2) против O (n) медленнее.Чтобы избежать « однако » в ответе Эрандака в сочетании с ответами Даниэля и Салмана, можно использовать один из следующих «обходных путей раздела»
Ранжирование разделов в третьем варианте в этом фрагменте кода будет возвращать непрерывные ранжирующие числа. это приведет к структуре данных, похожей на
rank() over partition by
результат. В качестве примера см. Ниже. В частности, partitionSequence всегда будет начинаться с 1 для каждого нового partitionRank , используя этот метод:источник
источник