Fungsi peringkat di MySQL


155

Saya perlu mencari tahu peringkat pelanggan. Di sini saya menambahkan query SQL standar ANSI yang sesuai untuk kebutuhan saya. Tolong bantu saya untuk mengubahnya ke MySQL.

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

Apakah ada fungsi untuk mengetahui peringkat di MySQL?

Jawaban:


266

Salah satu opsi adalah menggunakan variabel peringkat, seperti yang berikut:

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

Bagian ini (SELECT @curRank := 0)memungkinkan inisialisasi variabel tanpa memerlukan SETperintah terpisah .

Kasus cobaan:

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

Hasil:

+------------+------+--------+------+
| 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 untuk inisialisasi inline yang licik, itu trik yang bagus.
Charles

28
Bukankah dia meminta partisi? Pemahaman saya tentang partisi adalah bahwa set hasil akan memiliki peringkat yang terpisah untuk pria dan wanita.
Jesse Dhillon

2
@Jesse: Jika itu masalahnya, saya baru-baru ini menjawab pertanyaan serupa: stackoverflow.com/questions/3162389/multiple-ranks-in-one-table
Daniel Vassallo

6
Bagaimana jika saya ingin memberi peringkat 4 untuk Anne dan Bob keduanya?
Fahim Parkar

8
Ini tidak menerapkan contoh dari pertanyaan karena merindukan partition by genderbagian dari fungsi analitis (yang "angka" nilai peringkat per jenis kelamin bukan untuk hasil keseluruhan)
a_horse_with_no_name

53

Berikut adalah solusi umum yang memberikan peringkat padat partisi ke baris. Ini menggunakan variabel pengguna:

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;

Perhatikan bahwa tugas variabel ditempatkan di dalam CASEekspresi. Ini (secara teori) menangani urutan masalah evaluasi. ItuIS NOT NULL ditambahkan untuk menangani konversi tipe data dan masalah korsleting.

PS: Dapat dengan mudah dikonversi menjadi nomor baris di atas partisi dengan menghapus semua kondisi yang memeriksa dasi.

| 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 di db <> biola


2
Solusi ini, atau solusi Mukesh, harus menjadi solusi yang benar. Meskipun secara teknis saya percaya solusi kalian berdua mewakili peringkat padat dan bukan peringkat biasa. Berikut adalah penjelasan yang baik tentang perbedaan: sqlservercurry.com/2009/04/… .
modulitos

Bisakah Anda memberi tahu kami bagaimana seharusnya kode .php? Saya mencoba mengikuti, tetapi kode di atas tidak berfungsi. Bagaimana cara memasukkan ke format .php?
pencipta

Solusi ini tidak terlalu umum; itu tidak akan berfungsi jika rank_column memiliki nilai 0. sqlfiddle.com/#!2/9c5dd/1
mike

1
@ Mike Tambahkan bagian ELSE ke pernyataan KASUS:ELSE @rank_count := @rank_count + 1
Pangeran Odame

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

52

Sementara peringkat jawaban yang paling banyak dipilih, itu tidak mempartisi, Anda bisa melakukan sendiri Gabung untuk mendapatkan semuanya juga dipartisi:

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

Gunakan Kasing

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

Jawaban :

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

ini adalah jawaban yang luar biasa karena saya perlu melakukan peringkat partisi. Terima kasih Pak!
Kim Stacks

IMO memiliki kompleksitas yang sama dengan subselect dalam jawaban @Sam Kidman: O (n ^ 2). Tapi tidak tahu apakah mungkin melakukannya dengan lebih baik di MySQL.
xmedeko

Lihatlah onlamp.com/pub/a/mysql/2007/03/29/… untuk tutorial yang bagus di sepanjang baris yang sama
ferics2

Bergabunglah sendiri untuk mendapatkan peringkat! Itu hebat. Akhirnya, solusi tanpa variabel dan tanpa fungsi jendela MySQL 8 . :)
Timo

24

Tweak dari versi Daniel untuk menghitung persentil bersama dengan peringkat. Juga dua orang dengan nilai yang sama akan mendapatkan peringkat yang sama.

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

Hasil kueri untuk data sampel -

+----+-------+------+---------------+---------------+-----------------+
| 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
Meskipun ini tidak benar-benar optimal dalam kinerja, itu luar biasa!
Gaspa79

18

Kombinasi jawaban Daniel dan Salman. Namun pangkat tidak akan memberikan urutan berlanjut dengan ikatan ada. Alih-alih itu melompat peringkat ke berikutnya. Jadi maksimum selalu mencapai jumlah baris.

    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;

Skema dan Uji Kasus:

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

Keluaran:

+------------+------+--------+------+--------------------------+-----------------+
| 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
Saya baru mengenal MySQL tetapi apakah solusi ini oke? Dalam MySQL docs mengatakan "urutan evaluasi untuk ekspresi yang melibatkan variabel pengguna tidak ditentukan." dev.mysql.com/doc/refman/5.7/en/user-variables.html
narduk

13

Dimulai dengan MySQL 8, Anda akhirnya dapat menggunakan fungsi jendela juga di MySQL: https://dev.mysql.com/doc/refman/8.0/id/window-functions.html

Permintaan Anda dapat ditulis dengan cara yang persis sama:

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

Tidak salah hanya tidak bekerja dengan versi SQL yang lebih lama. ditambah lagi itu agak copy dan melewati pertanyaannya sehingga tidak terasa cocok dengan jawabannya.
newdark-it

4
@ brand-it Bagi mereka yang menggunakan MySQL 8+, jawaban ini penting karena memberi tahu kami bahwa Rank sekarang tersedia. Jika saya tidak menggulir sejauh ini, saya akan menganggap jawaban sebelumnya adalah satu-satunya solusi.
Steve Smith

1
@SteveSmith Poin bagus, bagus untuk memiliki jawaban ini bagi mereka yang menggunakan versi MYSQL yang lebih baru.
newdark-it

Ya, saya berkecil hati dengan banyak jawaban dengan variabel pengguna dan blok logika. Versi baru MySQL memungkinkan melakukannya BANYAK sederhana dengan fungsi RANK () yang menawarkan pengelompokan built in berdasarkan partisi.
James Bond

5

@Sam, maksud Anda sangat bagus dalam konsep tapi saya pikir Anda salah mengerti apa yang dikatakan oleh dokumen MySQL pada halaman yang direferensikan - atau saya salah paham :-) - dan saya hanya ingin menambahkan ini sehingga jika seseorang merasa tidak nyaman dengan @ Jawaban Daniel mereka akan lebih diyakinkan atau setidaknya menggali lebih dalam.

Anda lihat di "@curRank := @curRank + 1 AS rank"dalam SELECTitu bukan "satu pernyataan", itu adalah satu "atom" bagian dari pernyataan itu sehingga harus aman.

Dokumen yang Anda referensi melanjutkan untuk memperlihatkan contoh-contoh di mana variabel yang ditentukan pengguna yang sama dalam 2 bagian (atom) pernyataan, misalnya, "SELECT @curRank, @curRank := @curRank + 1 AS rank" ,.

Orang mungkin berpendapat bahwa @curRankini digunakan dua kali dalam jawaban @ Daniel: (1) "@curRank := @curRank + 1 AS rank"dan (2)"(SELECT @curRank := 0) r" tetapi karena penggunaan kedua adalah bagian dariFROM klausa, saya cukup yakin itu dijamin untuk dievaluasi terlebih dahulu; pada dasarnya membuatnya menjadi pernyataan kedua, dan sebelumnya.

Bahkan, pada halaman dokumen MySQL yang sama yang Anda referensikan, Anda akan melihat solusi yang sama di komentar - itu bisa dari mana @Daniel mendapatkannya; ya, saya tahu bahwa itu adalah komentar tetapi itu adalah komentar di halaman dokumen resmi dan itu memang membawa beban.


Semua ini tidak dibenarkan oleh dokumentasi. Itu hanya spekulasi (kabur). Seperti semua jawaban baik menggunakan & menulis variabel yang sama, yang dikatakan manual secara eksplisit tidak didefinisikan, meskipun manual memang memiliki banyak teks tidak membantu kembali apa yang mungkin bekerja seperti yang Anda harapkan, tanpa mengatakan apa yang menurut Anda harapkan atau apa yang digunakan deskripsi perilaku tidak dijamin adalah. PS Pada 8.0 tugas variabel di luar SET sudah tidak digunakan lagi.
philipxy

4

Solusi paling lurus ke depan untuk menentukan peringkat nilai yang diberikan adalah dengan menghitung jumlah nilai sebelum itu. Misalkan kita memiliki nilai-nilai berikut:

10 20 30 30 30 40
  • Semua 30nilai dipertimbangkan ke-3
  • Semua 40nilai dianggap ke-6 (peringkat) atau ke - 4 (peringkat padat)

Sekarang kembali ke pertanyaan awal. Berikut adalah beberapa contoh data yang diurutkan seperti dijelaskan dalam OP (peringkat yang diharapkan ditambahkan di sebelah kanan):

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

Untuk menghitung RANK() OVER (PARTITION BY Gender ORDER BY Age)untuk Sarah , Anda dapat menggunakan kueri ini:

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

Untuk menghitung RANK() OVER (PARTITION BY Gender ORDER BY Age)untuk Semua baris Anda dapat menggunakan query ini:

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

Dan inilah hasilnya (nilai gabungan ditambahkan di sebelah kanan):

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

Jika Anda ingin peringkat hanya satu orang, Anda dapat melakukan hal berikut:

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

Peringkat ini sesuai dengan fungsi RANK oracle (Di mana jika Anda memiliki orang dengan usia yang sama mereka mendapatkan peringkat yang sama, dan peringkat setelah itu adalah non-berturut-turut).

Ini sedikit lebih cepat daripada menggunakan salah satu solusi di atas dalam subquery dan memilih dari itu untuk mendapatkan peringkat satu orang.

Ini dapat digunakan untuk memberi peringkat pada semua orang tetapi lebih lambat dari solusi di atas.

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

Ini mungkin menjadi jauh lebih lambat daripada solusi di atas ketika jumlah baris dalam Persontabel bertambah. Ini lebih lambat O (n ^ 2) vs O (n) .
xmedeko

2

Untuk menghindari " namun " dalam jawaban Erandac dalam kombinasi jawaban Daniel dan Salman, orang dapat menggunakan salah satu dari "pemecahan masalah partisi" berikut ini

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

Peringkat partisi dalam varian ke-3 dalam cuplikan kode ini akan menghasilkan angka peringkat berkelanjutan. ini akan mengarah pada struktur data yang mirip dengan rank() over partition byhasilnya. Sebagai contoh, lihat di bawah. Secara khusus, partisiSequence akan selalu dimulai dengan 1 untuk setiap partisiRank baru , menggunakan metode ini:

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');
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.