Jedną z opcji jest użycie zmiennej rankingowej, takiej jak:
SELECT first_name,
age,
gender,
@curRank := @curRank + 1 AS rank
FROM person p, (SELECT @curRank := 0) r
ORDER BY age;
(SELECT @curRank := 0)
Część pozwala zmiennej inicjalizacji bez potrzeby dodatkowego SET
polecenia.
Przypadek testowy:
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');
Wynik:
+------------+------+--------+------+
| 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
część funkcji analitycznej (która „numeruje” wartość rangi według płci, a nie dla ogólnego wyniku)Oto ogólne rozwiązanie, które przypisuje wierszom gęstą rangę nad partycjami. Wykorzystuje zmienne użytkownika:
Zauważ, że przypisania zmiennych są umieszczone wewnątrz
CASE
wyrażenia. To (w teorii) dba o kolejność ewaluacji.IS NOT NULL
Dodaje obsługiwać typ danych konwersji i krótkie spięcie problemów.PS: Można go łatwo przekonwertować na numer wiersza na partycji, usuwając wszystkie warunki, które sprawdzają remis.
Demo na db <> fiddle
źródło
ELSE @rank_count := @rank_count + 1
ORDER BY gender, age DESC
?Chociaż odpowiedź, która uzyskała najwięcej głosów, jest klasyfikowana, nie dzieli się na partycje, możesz dołączyć do siebie, aby całość została również podzielona:
Przypadek użycia
Odpowiedź :
źródło
Ulepszenie wersji Daniela, aby obliczyć percentyl wraz z rangą. Również dwie osoby z takimi samymi ocenami otrzymają tę samą rangę.
Wyniki zapytania o przykładowe dane -
źródło
Połączenie odpowiedzi Daniela i Salmana. Jednak ranga nie zostanie określona, ponieważ istnieje sekwencja kontynuacji z remisami. Zamiast tego pomija rangę do następnej. Tak więc maksymalna zawsze osiąga liczbę wierszy.
Schemat i przypadek testowy:
Wynik:
źródło
Począwszy od MySQL 8, możesz wreszcie korzystać z funkcji okna także w MySQL: https://dev.mysql.com/doc/refman/8.0/en/window-functions.html
Twoje zapytanie można zapisać dokładnie w ten sam sposób:
źródło
@Sam, twój punkt widzenia jest doskonały w koncepcji, ale myślę, że źle zrozumiałeś, co dokumentacja MySQL mówi na podanej stronie - lub źle zrozumiałem :-) - i chciałem to dodać, aby jeśli ktoś poczuł się nieswojo z @ Daniel odpowiada, że będą bardziej uspokojeni lub przynajmniej kopią trochę głębiej.
Widzisz
"@curRank := @curRank + 1 AS rank"
wnętrzeSELECT
nie jest „jedną instrukcją”, jest jedną „atomową” częścią instrukcji, więc powinno być bezpieczne.Dokument, do którego się odwołujesz, pokazuje przykłady, w których ta sama zmienna zdefiniowana przez użytkownika w 2 (atomowych) częściach instrukcji, na przykład
"SELECT @curRank, @curRank := @curRank + 1 AS rank"
.Można by argumentować, że
@curRank
jest ono użyte dwukrotnie w odpowiedzi @ Daniela: (1) the"@curRank := @curRank + 1 AS rank"
i (2) the,"(SELECT @curRank := 0) r"
ale ponieważ drugie użycie jest częściąFROM
klauzuli, jestem prawie pewien, że zostanie ocenione jako pierwsze; zasadniczo czyniąc to drugim i poprzedzającym stwierdzeniem.W rzeczywistości na tej samej stronie z dokumentacją MySQL, do której się odwołałeś, zobaczysz to samo rozwiązanie w komentarzach - może to być miejsce, skąd wziął je @Daniel; tak, wiem, że to komentarze, ale to komentarze na oficjalnej stronie z dokumentacją i to ma jakąś wagę.
źródło
Najprostszym sposobem określenia rangi danej wartości jest policzenie liczby wartości przed nią. Załóżmy, że mamy następujące wartości:
30
wartości są uważane za trzecie40
wartości są uważane za szóste (ranga) lub 4 (gęsta ranga)Wróćmy teraz do pierwotnego pytania. Oto kilka przykładowych danych, które są posortowane zgodnie z opisem w PO (oczekiwane rangi są dodane po prawej stronie):
Aby obliczyć
RANK() OVER (PARTITION BY Gender ORDER BY Age)
dla Sarah , możesz użyć tego zapytania:Aby obliczyć
RANK() OVER (PARTITION BY Gender ORDER BY Age)
dla wszystkich wierszy, możesz użyć tego zapytania:A oto wynik (połączone wartości są dodawane po prawej stronie):
źródło
Jeśli chcesz umieścić w rankingu tylko jedną osobę, możesz wykonać następujące czynności:
Ranking ten odpowiada funkcji wyroczni RANK (gdzie, jeśli masz ludzi w tym samym wieku, uzyskują tę samą rangę, a kolejność nie jest kolejna).
Jest to trochę szybsze niż użycie jednego z powyższych rozwiązań w podzapytaniu i wybranie z niego, aby uzyskać ranking jednej osoby.
Można to wykorzystać do uszeregowania wszystkich, ale jest wolniejsze niż powyższe rozwiązania.
źródło
Person
tabeli wzrośnie. To O (n ^ 2) vs O (n) wolniej.Aby uniknąć „ jednak ” w odpowiedzi Erandaca w połączeniu z odpowiedziami Daniela i Salmana, można użyć jednego z następujących „obejść podziału”
Ranking partycji w 3. wariancie w tym fragmencie kodu zwróci ciągłe numery rankingowe. doprowadzi to do struktury danych podobnej do
rank() over partition by
wyniku. Jako przykład patrz poniżej. W szczególności, partitionSequence zawsze będzie rozpoczynać się od 1 dla każdego nowego rankingu partycji , używając tej metody:źródło
źródło