Rangfunktion in MySQL


155

Ich muss den Rang der Kunden herausfinden. Hier füge ich die entsprechende ANSI-Standard-SQL-Abfrage für meine Anforderung hinzu. Bitte helfen Sie mir, es in MySQL zu konvertieren.

SELECT RANK() OVER (PARTITION BY Gender ORDER BY Age) AS [Partition by Gender], 
  FirstName, 
  Age,
  Gender 
FROM Person

Gibt es eine Funktion, um den Rang in MySQL herauszufinden?

Antworten:


266

Eine Möglichkeit besteht darin, eine Rangvariable wie die folgende zu verwenden:

SELECT    first_name,
          age,
          gender,
          @curRank := @curRank + 1 AS rank
FROM      person p, (SELECT @curRank := 0) r
ORDER BY  age;

Das (SELECT @curRank := 0)Teil ermöglicht die Variableninitialisierung, ohne dass eine separate erforderlich istSET Befehl .

Testfall:

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');

Ergebnis:

+------------+------+--------+------+
| 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)

52
+1 für die umständliche Inline-Initialisierung, das ist ein schöner Trick.
Charles

28
Hat er nicht um eine Teilung gebeten? Mein Verständnis von Partitionen ist, dass die Ergebnismenge getrennte Rangfolgen für Männer und Frauen haben würde.
Jesse Dhillon

2
@ Jesse: Wenn das der Fall ist, habe ich kürzlich eine ähnliche Frage beantwortet: stackoverflow.com/questions/3162389/multiple-ranks-in-one-table
Daniel Vassallo

6
Was ist, wenn ich Anne und Bob den Rang 4 geben möchte?
Fahim Parkar

8
Dies implementiert das Beispiel aus der Frage nicht, da der partition by genderTeil der Analysefunktion fehlt (der den
Rangwert

53

Hier ist eine generische Lösung, die Zeilen einen dichten Rang über der Partition zuweist. Es werden Benutzervariablen verwendet:

CREATE TABLE person (
    id INT NOT NULL PRIMARY KEY,
    firstname VARCHAR(10),
    gender VARCHAR(1),
    age INT
);

INSERT INTO person (id, firstname, gender, age) VALUES
(1,  'Adams',  'M', 33),
(2,  'Matt',   'M', 31),
(3,  'Grace',  'F', 25),
(4,  'Harry',  'M', 20),
(5,  'Scott',  'M', 30),
(6,  'Sarah',  'F', 30),
(7,  'Tony',   'M', 30),
(8,  'Lucy',   'F', 27),
(9,  'Zoe',    'F', 30),
(10, 'Megan',  'F', 26),
(11, 'Emily',  'F', 20),
(12, 'Peter',  'M', 20),
(13, 'John',   'M', 21),
(14, 'Kate',   'F', 35),
(15, 'James',  'M', 32),
(16, 'Cole',   'M', 25),
(17, 'Dennis', 'M', 27),
(18, 'Smith',  'M', 35),
(19, 'Zack',   'M', 35),
(20, 'Jill',   'F', 25);

SELECT person.*, @rank := CASE
    WHEN @partval = gender AND @rankval = age THEN @rank
    WHEN @partval = gender AND (@rankval := age) IS NOT NULL THEN @rank + 1
    WHEN (@partval := gender) IS NOT NULL AND (@rankval := age) IS NOT NULL THEN 1
END AS rnk
FROM person, (SELECT @rank := NULL, @partval := NULL, @rankval := NULL) AS x
ORDER BY gender, age;

Beachten Sie, dass die Variablenzuweisungen innerhalb des CASEAusdrucks platziert werden. Dies kümmert sich (theoretisch) um die Reihenfolge der Bewertung. DasIS NOT NULL wird hinzugefügt, um Probleme mit der Datentypkonvertierung und dem Kurzschluss zu lösen.

PS: Es kann einfach über die Partition in eine Zeilennummer konvertiert werden, indem alle Bedingungen entfernt werden, die auf Gleichheit prüfen.

| id | firstname | gender | age | rank |
|----|-----------|--------|-----|------|
| 11 | Emily     | F      | 20  | 1    |
| 20 | Jill      | F      | 25  | 2    |
| 3  | Grace     | F      | 25  | 2    |
| 10 | Megan     | F      | 26  | 3    |
| 8  | Lucy      | F      | 27  | 4    |
| 6  | Sarah     | F      | 30  | 5    |
| 9  | Zoe       | F      | 30  | 5    |
| 14 | Kate      | F      | 35  | 6    |
| 4  | Harry     | M      | 20  | 1    |
| 12 | Peter     | M      | 20  | 1    |
| 13 | John      | M      | 21  | 2    |
| 16 | Cole      | M      | 25  | 3    |
| 17 | Dennis    | M      | 27  | 4    |
| 7  | Tony      | M      | 30  | 5    |
| 5  | Scott     | M      | 30  | 5    |
| 2  | Matt      | M      | 31  | 6    |
| 15 | James     | M      | 32  | 7    |
| 1  | Adams     | M      | 33  | 8    |
| 18 | Smith     | M      | 35  | 9    |
| 19 | Zack      | M      | 35  | 9    |

Demo auf db <> fiddle


2
Diese Lösung oder Mukeshs Lösung sollte die richtige Lösung sein. Obwohl ich technisch gesehen glaube, dass die Lösungen von euch beiden einen dichten Rang und keinen regulären Rang darstellen. Hier ist eine gute Erklärung der Unterschiede: sqlservercurry.com/2009/04/… .
Modulitos

Können Sie uns auch mitteilen, wie der .php-Code genau sein soll? Ich habe versucht zu folgen, aber der obige Code funktioniert nicht. Wie gebe ich in das PHP-Format ein?
Schöpfer

Diese Lösung ist nicht sehr allgemein; es wird nicht funktionieren, wenn rank_column einen Wert von 0 hat. sqlfiddle.com/#!2/9c5dd/1
mike

1
@mike Fügen Sie der CASE-Anweisung einen ELSE-Abschnitt hinzu:ELSE @rank_count := @rank_count + 1
Prince Odame

1
@abhash ORDER BY gender, age DESC?
Salman A

52

Während die am besten bewertete Antwort rangiert, wird sie nicht partitioniert. Sie können einen Self-Join durchführen, um das Ganze auch zu partitionieren:

SELECT    a.first_name,
      a.age,
      a.gender,
        count(b.age)+1 as rank
FROM  person a left join person b on a.age>b.age and a.gender=b.gender 
group by  a.first_name,
      a.age,
      a.gender

Anwendungsfall

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');

Antwort :

Bill    32  M   4
Bob     25  M   2
Jack    30  M   3
Nick    22  M   1
Steve   36  M   5
Anne    25  F   3
Jane    20  F   2
Kathy   18  F   1

Dies ist eine wunderbare Antwort, gerade weil ich ein Partitionsranking durchführen muss. Danke mein Herr!
Kim Stacks

IMO hat es die gleiche Komplexität wie die Unterauswahl in der Antwort von @Sam Kidman: O (n ^ 2). Aber ich weiß nicht, ob es in MySQL besser geht.
Xmedeko

Unter onlamp.com/pub/a/mysql/2007/03/29/… finden Sie ein großartiges Tutorial in diesem Sinne
ferics2,

Mach mit, um den Rang zu erreichen! Das ist großartig. Endlich eine Lösung ohne Variablen und ohne MySQL 8-Fensterfunktionen . :)
Timo

24

Eine Optimierung von Daniels Version, um das Perzentil zusammen mit dem Rang zu berechnen. Auch zwei Personen mit den gleichen Noten erhalten den gleichen Rang.

set @totalStudents = 0;
select count(*) into @totalStudents from marksheets;
SELECT id, score, @curRank := IF(@prevVal=score, @curRank, @studentNumber) AS rank, 
@percentile := IF(@prevVal=score, @percentile, (@totalStudents - @studentNumber + 1)/(@totalStudents)*100),
@studentNumber := @studentNumber + 1 as studentNumber, 
@prevVal:=score
FROM marksheets, (
SELECT @curRank :=0, @prevVal:=null, @studentNumber:=1, @percentile:=100
) r
ORDER BY score DESC

Ergebnisse der Abfrage nach Beispieldaten -

+----+-------+------+---------------+---------------+-----------------+
| id | score | rank | percentile    | studentNumber | @prevVal:=score |
+----+-------+------+---------------+---------------+-----------------+
| 10 |    98 |    1 | 100.000000000 |             2 |              98 |
|  5 |    95 |    2 |  90.000000000 |             3 |              95 |
|  6 |    91 |    3 |  80.000000000 |             4 |              91 |
|  2 |    91 |    3 |  80.000000000 |             5 |              91 |
|  8 |    90 |    5 |  60.000000000 |             6 |              90 |
|  1 |    90 |    5 |  60.000000000 |             7 |              90 |
|  9 |    84 |    7 |  40.000000000 |             8 |              84 |
|  3 |    83 |    8 |  30.000000000 |             9 |              83 |
|  4 |    72 |    9 |  20.000000000 |            10 |              72 |
|  7 |    60 |   10 |  10.000000000 |            11 |              60 |
+----+-------+------+---------------+---------------+-----------------+

1
Auch wenn dies in der Leistung nicht wirklich optimal ist, ist es fantastisch!
Gaspa79

18

Kombination von Daniels und Salmans Antwort. Der Rang wird jedoch nicht angegeben, da eine fortlaufende Sequenz mit Bindungen besteht. Stattdessen wird der Rang zum nächsten übersprungen. So erreichen Sie maximal immer die Zeilenanzahl.

    SELECT    first_name,
              age,
              gender,
              IF(age=@_last_age,@curRank:=@curRank,@curRank:=@_sequence) AS rank,
              @_sequence:=@_sequence+1,@_last_age:=age
    FROM      person p, (SELECT @curRank := 1, @_sequence:=1, @_last_age:=0) r
    ORDER BY  age;

Schema und Testfall:

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');
INSERT INTO person VALUES (9, 'Kamal', 25, 'M');
INSERT INTO person VALUES (10, 'Saman', 32, 'M');

Ausgabe:

+------------+------+--------+------+--------------------------+-----------------+
| first_name | age  | gender | rank | @_sequence:=@_sequence+1 | @_last_age:=age |
+------------+------+--------+------+--------------------------+-----------------+
| Kathy      |   18 | F      |    1 |                        2 |              18 |
| Jane       |   20 | F      |    2 |                        3 |              20 |
| Nick       |   22 | M      |    3 |                        4 |              22 |
| Kamal      |   25 | M      |    4 |                        5 |              25 |
| Anne       |   25 | F      |    4 |                        6 |              25 |
| Bob        |   25 | M      |    4 |                        7 |              25 |
| Jack       |   30 | M      |    7 |                        8 |              30 |
| Bill       |   32 | M      |    8 |                        9 |              32 |
| Saman      |   32 | M      |    8 |                       10 |              32 |
| Steve      |   36 | M      |   10 |                       11 |              36 |
+------------+------+--------+------+--------------------------+-----------------+

1
Ich bin neu in MySQL, aber ist diese Lösung in Ordnung? In MySQL-Dokumenten heißt es: "Die Reihenfolge der Auswertung für Ausdrücke mit Benutzervariablen ist undefiniert." dev.mysql.com/doc/refman/5.7/en/user-variables.html
narduk

13

Ab MySQL 8 können Sie endlich auch in MySQL Fensterfunktionen verwenden: https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

Ihre Anfrage kann genauso geschrieben werden:

SELECT RANK() OVER (PARTITION BY Gender ORDER BY Age) AS `Partition by Gender`, 
  FirstName, 
  Age,
  Gender 
FROM Person

Es ist nicht falsch, funktioniert einfach nicht mit älteren Versionen von SQL. Außerdem war es eine Art Kopie und Vergangenheit seiner Frage, so dass es sich nicht so anfühlt, als würde es zur Antwort passen.
Newdark-It

4
@ brand-it Für diejenigen unter MySQL 8+ ist diese Antwort wichtig, da sie uns wissen lässt, dass Rank jetzt verfügbar ist. Wenn ich nicht so weit nach unten gescrollt hätte, würde ich annehmen, dass die früheren Antworten die einzige Lösung waren.
Steve Smith

1
@SteveSmith Guter Punkt, es ist schön, diese Antwort für diejenigen zu haben, die die neuere Version von MYSQL verwenden.
Newdark-It

Ja, ich bin entmutigt von vielen Antworten mit den Benutzervariablen und Logikblöcken. Eine neue Version von MySQL ermöglicht es VIEL einfach mit der RANK () -Funktion, die eine integrierte Gruppierung nach Partitionen bietet.
James Bond

5

@Sam, Ihr Punkt ist im Konzept ausgezeichnet, aber ich denke, Sie haben falsch verstanden, was die MySQL-Dokumente auf der referenzierten Seite sagen - oder ich verstehe falsch :-) - und ich wollte dies nur hinzufügen, damit sich jemand mit dem @ unwohl fühlt Daniels Antwort, sie werden beruhigter sein oder zumindest etwas tiefer graben.

Sie sehen, dass das "@curRank := @curRank + 1 AS rank"Innere SELECTnicht "eine Aussage" ist, sondern ein "atomarer" Teil der Aussage, also sollte es sicher sein.

Das Dokument, auf das Sie verweisen, zeigt Beispiele, in denen dieselbe benutzerdefinierte Variable in zwei (atomaren) Teilen der Anweisung verwendet wird, z. "SELECT @curRank, @curRank := @curRank + 1 AS rank" .

Man könnte argumentieren, dass dies @curRankin @ Daniels Antwort zweimal verwendet wird: (1) die "@curRank := @curRank + 1 AS rank"und (2) die, "(SELECT @curRank := 0) r"aber da die zweite Verwendung Teil der istFROM Klausel ist, bin ich mir ziemlich sicher, dass sie garantiert zuerst bewertet wird; im Wesentlichen macht es eine zweite und vorhergehende Aussage.

Tatsächlich sehen Sie auf derselben MySQL-Dokumentenseite, auf die Sie verwiesen haben, dieselbe Lösung in den Kommentaren - es könnte sein, woher @Daniel sie hat; Ja, ich weiß, dass es die Kommentare sind, aber es sind Kommentare auf der offiziellen Dokumentenseite und das hat etwas Gewicht.


Nichts davon wird durch die Dokumentation gerechtfertigt. Es ist nur (unscharfe) Spekulation. Wie alle Antworten, bei denen dieselbe Variable verwendet und geschrieben wird, die im Handbuch ausdrücklich nicht definiert ist, obwohl das Handbuch viele nicht hilfreiche Texte enthält, was möglicherweise so funktioniert, wie Sie es erwarten, ohne zu sagen, was Sie erwarten oder welchen Nutzen es hat Eine Beschreibung des nicht garantierten Verhaltens ist. PS Ab 8.0 ist die Variablenzuweisung außerhalb von SET veraltet.
Philipxy

4

Die einfachste Lösung, um den Rang eines bestimmten Werts zu bestimmen, besteht darin, die Anzahl der Werte davor zu zählen . Angenommen, wir haben die folgenden Werte:

10 20 30 30 30 40
  • Alle 30Werte gelten als 3 ..
  • Alles 40 Werte werden als 6. (Rang) oder 4. (dichter Rang) betrachtet.

Nun zurück zur ursprünglichen Frage. Hier sind einige Beispieldaten, die wie in OP beschrieben sortiert sind (erwartete Ränge werden rechts hinzugefügt):

+------+-----------+------+--------+    +------+------------+
| id   | firstname | age  | gender |    | rank | dense_rank |
+------+-----------+------+--------+    +------+------------+
|   11 | Emily     |   20 | F      |    |    1 |          1 |
|    3 | Grace     |   25 | F      |    |    2 |          2 |
|   20 | Jill      |   25 | F      |    |    2 |          2 |
|   10 | Megan     |   26 | F      |    |    4 |          3 |
|    8 | Lucy      |   27 | F      |    |    5 |          4 |
|    6 | Sarah     |   30 | F      |    |    6 |          5 |
|    9 | Zoe       |   30 | F      |    |    6 |          5 |
|   14 | Kate      |   35 | F      |    |    8 |          6 |
|    4 | Harry     |   20 | M      |    |    1 |          1 |
|   12 | Peter     |   20 | M      |    |    1 |          1 |
|   13 | John      |   21 | M      |    |    3 |          2 |
|   16 | Cole      |   25 | M      |    |    4 |          3 |
|   17 | Dennis    |   27 | M      |    |    5 |          4 |
|    5 | Scott     |   30 | M      |    |    6 |          5 |
|    7 | Tony      |   30 | M      |    |    6 |          5 |
|    2 | Matt      |   31 | M      |    |    8 |          6 |
|   15 | James     |   32 | M      |    |    9 |          7 |
|    1 | Adams     |   33 | M      |    |   10 |          8 |
|   18 | Smith     |   35 | M      |    |   11 |          9 |
|   19 | Zack      |   35 | M      |    |   11 |          9 |
+------+-----------+------+--------+    +------+------------+

Zu berechnen RANK() OVER (PARTITION BY Gender ORDER BY Age)für Sarah, können Sie diese Abfrage verwenden:

SELECT COUNT(id) + 1 AS rank, COUNT(DISTINCT age) + 1 AS dense_rank
FROM testdata
WHERE gender = (SELECT gender FROM testdata WHERE id = 6)
AND age < (SELECT age FROM testdata WHERE id = 6)

+------+------------+
| rank | dense_rank |
+------+------------+
|    6 |          5 |
+------+------------+

Zu berechnen RANK() OVER (PARTITION BY Gender ORDER BY Age)für alle Zeilen, können Sie diese Abfrage verwenden:

SELECT testdata.id, COUNT(lesser.id) + 1 AS rank, COUNT(DISTINCT lesser.age) + 1 AS dense_rank
FROM testdata
LEFT JOIN testdata AS lesser ON lesser.age < testdata.age AND lesser.gender = testdata.gender
GROUP BY testdata.id

Und hier ist das Ergebnis (verbundene Werte werden rechts hinzugefügt):

+------+------+------------+    +-----------+-----+--------+
| id   | rank | dense_rank |    | firstname | age | gender |
+------+------+------------+    +-----------+-----+--------+
|   11 |    1 |          1 |    | Emily     |  20 | F      |
|    3 |    2 |          2 |    | Grace     |  25 | F      |
|   20 |    2 |          2 |    | Jill      |  25 | F      |
|   10 |    4 |          3 |    | Megan     |  26 | F      |
|    8 |    5 |          4 |    | Lucy      |  27 | F      |
|    6 |    6 |          5 |    | Sarah     |  30 | F      |
|    9 |    6 |          5 |    | Zoe       |  30 | F      |
|   14 |    8 |          6 |    | Kate      |  35 | F      |
|    4 |    1 |          1 |    | Harry     |  20 | M      |
|   12 |    1 |          1 |    | Peter     |  20 | M      |
|   13 |    3 |          2 |    | John      |  21 | M      |
|   16 |    4 |          3 |    | Cole      |  25 | M      |
|   17 |    5 |          4 |    | Dennis    |  27 | M      |
|    5 |    6 |          5 |    | Scott     |  30 | M      |
|    7 |    6 |          5 |    | Tony      |  30 | M      |
|    2 |    8 |          6 |    | Matt      |  31 | M      |
|   15 |    9 |          7 |    | James     |  32 | M      |
|    1 |   10 |          8 |    | Adams     |  33 | M      |
|   18 |   11 |          9 |    | Smith     |  35 | M      |
|   19 |   11 |          9 |    | Zack      |  35 | M      |
+------+------+------------+    +-----------+-----+--------+

3

Wenn Sie nur eine Person bewerten möchten, können Sie Folgendes tun:

SELECT COUNT(Age) + 1
 FROM PERSON
WHERE(Age < age_to_rank)

Diese Rangfolge entspricht der Orakel-RANG-Funktion (Wenn Personen mit demselben Alter denselben Rang erhalten und die Rangfolge danach nicht fortlaufend ist).

Es ist ein bisschen schneller als die Verwendung einer der oben genannten Lösungen in einer Unterabfrage und die Auswahl daraus, um das Ranking einer Person zu erhalten.

Dies kann verwendet werden, um alle zu bewerten, ist jedoch langsamer als die oben genannten Lösungen.

SELECT
  Age AS age_var,
(
  SELECT COUNT(Age) + 1
  FROM Person
  WHERE (Age < age_var)
 ) AS rank
 FROM Person

Es kann viel langsamer werden als bei den oben genannten Lösungen, wenn die Anzahl der Zeilen in der PersonTabelle zunimmt. Es ist O (n ^ 2) gegen O (n) langsamer.
Xmedeko

2

Um das " jedoch " in Erandacs Antwort in Kombination mit Daniels und Salmans Antworten zu vermeiden , kann eine der folgenden "Partition Workarounds" verwendet werden.

SELECT customerID, myDate

  -- partition ranking works only with CTE / from MySQL 8.0 on
  , RANK() OVER (PARTITION BY customerID ORDER BY dateFrom) AS rank, 

  -- Erandac's method in combination of Daniel's and Salman's
  -- count all items in sequence, maximum reaches row count.
  , IF(customerID=@_lastRank, @_curRank:=@_curRank, @_curRank:=@_sequence+1) AS sequenceRank
  , @_sequence:=@_sequence+1 as sequenceOverAll

  -- Dense partition ranking, works also with MySQL 5.7
  -- remember to set offset values in from clause
  , IF(customerID=@_lastRank, @_nxtRank:=@_nxtRank, @_nxtRank:=@_nxtRank+1 ) AS partitionRank
  , IF(customerID=@_lastRank, @_overPart:=@_overPart+1, @_overPart:=1 ) AS partitionSequence

  , @_lastRank:=customerID
FROM myCustomers, 
  (SELECT @_curRank:=0, @_sequence:=0, @_lastRank:=0, @_nxtRank:=0, @_overPart:=0 ) r
ORDER BY customerID, myDate

Das Partitionsranking in der 3. Variante in diesem Code-Snippet gibt fortlaufende Ranking-Nummern zurück. Dies führt zu einer Datenstruktur ähnlich dem rank() over partition byErgebnis. Als Beispiel siehe unten. Insbesondere beginnt die partitionSequence immer mit 1 für jeden neuen partitionRank , wobei folgende Methode verwendet wird:

customerID    myDate   sequenceRank (Erandac)
                          |    sequenceOverAll
                          |     |   partitionRank
                          |     |     | partitionSequence
                          |     |     |    | lastRank
... lines ommitted for clarity
40    09.11.2016 11:19    1     44    1   44    40
40    09.12.2016 12:08    1     45    1   45    40
40    09.12.2016 12:08    1     46    1   46    40
40    09.12.2016 12:11    1     47    1   47    40
40    09.12.2016 12:12    1     48    1   48    40
40    13.10.2017 16:31    1     49    1   49    40
40    15.10.2017 11:00    1     50    1   50    40
76    01.07.2015 00:24    51    51    2    1    76
77    04.08.2014 13:35    52    52    3    1    77
79    15.04.2015 20:25    53    53    4    1    79
79    24.04.2018 11:44    53    54    4    2    79
79    08.10.2018 17:37    53    55    4    3    79
117   09.07.2014 18:21    56    56    5    1   117
119   26.06.2014 13:55    57    57    6    1   119
119   02.03.2015 10:23    57    58    6    2   119
119   12.10.2015 10:16    57    59    6    3   119
119   08.04.2016 09:32    57    60    6    4   119
119   05.10.2016 12:41    57    61    6    5   119
119   05.10.2016 12:42    57    62    6    6   119
...

0
select id,first_name,gender,age,
rank() over(partition by gender order by age) rank_g
from person

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');
INSERT INTO person VALUES (9,'AKSH',32,'M');
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.