Chức năng xếp hạng trong MySQL


155

Tôi cần tìm ra thứ hạng của khách hàng. Ở đây tôi đang thêm truy vấn SQL tiêu chuẩn ANSI tương ứng cho yêu cầu của tôi. Xin hãy giúp tôi chuyển đổi nó sang MySQL.

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

Có chức năng nào để tìm ra thứ hạng trong MySQL không?

Câu trả lời:


266

Một tùy chọn là sử dụng biến xếp hạng, chẳng hạn như sau:

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

Phần (SELECT @curRank := 0)cho phép khởi tạo biến mà không yêu cầu một SETlệnh riêng .

Trường hợp thử nghiệm:

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

Kết quả:

+------------+------+--------+------+
| 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 cho khởi tạo nội tuyến lệch lạc, đó là một mẹo hay.
Charles

28
Anh ấy không yêu cầu một phân vùng mặc dù? Sự hiểu biết của tôi về các phân vùng là tập kết quả sẽ có thứ hạng riêng cho nam và nữ.
Jesse Dhillon

2
@Jlie: Nếu đó là trường hợp, gần đây tôi đã trả lời một câu hỏi tương tự: stackoverflow.com/questions/3162389/multipl-ranks-in-one-table
Daniel Vassallo

6
Nếu tôi muốn xếp hạng 4 cho Anne và Bob thì sao?
Fahim Parkar

8
Điều này không triển khai ví dụ từ câu hỏi vì nó bỏ lỡ partition by gendermột phần của chức năng phân tích ("số" giá trị xếp hạng theo giới tính không cho kết quả tổng thể)
a_horse_with_no_name

53

Đây là một giải pháp chung gán thứ hạng dày đặc trên phân vùng cho các hàng. Nó sử dụng các biến người dùng:

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;

Lưu ý rằng các bài tập biến được đặt bên trong CASEbiểu thức. Điều này (về lý thuyết) quan tâm đến thứ tự của vấn đề đánh giá. Nó IS NOT NULLđược thêm vào để xử lý các vấn đề chuyển đổi kiểu dữ liệu và ngắn mạch.

PS: Nó có thể dễ dàng được chuyển đổi thành số hàng trên phân vùng bằng cách loại bỏ tất cả các điều kiện kiểm tra cà vạt.

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

Bản trình diễn trên db <> fiddle


2
Giải pháp này, hoặc giải pháp của Mukesh, nên là giải pháp chính xác. Mặc dù về mặt kỹ thuật tôi tin rằng cả hai giải pháp của các bạn đại diện cho một thứ hạng dày đặc và không phải là một thứ hạng thông thường. Đây là một lời giải thích tốt về sự khác biệt: sqlservercurry.com/2009/04/ .
modulitos

Bạn cũng có thể cho chúng tôi biết chính xác mã .php phải như thế nào không? Tôi đã cố gắng làm theo, nhưng mã trên không hoạt động. Làm thế nào để nhập vào định dạng .php?
người tạo

Giải pháp này không chung chung lắm; nó sẽ không hoạt động nếu rank_column có giá trị 0. sqlfiddle.com/#!2/9c5dd/1
mike

1
@mike Thêm phần ELSE vào câu lệnh CASE:ELSE @rank_count := @rank_count + 1
Prince Odame

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

52

Mặc dù các câu trả lời được xếp hạng cao nhất, nó không phân vùng, Bạn có thể tự tham gia để có được toàn bộ nội dung được phân vùng:

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

Ca sử dụng

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

Trả lời :

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

Đây là một câu trả lời tuyệt vời chính xác bởi vì tôi cần phải thực hiện xếp hạng phân vùng. Cảm ơn ngài!
Kim Stacks

IMO nó có độ phức tạp tương tự như chọn trong câu trả lời của @Sam Kidman: O (n ^ 2). Nhưng dunno biết nếu có thể làm điều đó tốt hơn trong MySQL.
xmedeko

Hãy xem onlamp.com/pub/a/mysql/2007/03/29/ cho một hướng dẫn tuyệt vời trên cùng một dòng
ferics2

Tự tham gia để có được thứ hạng! Thật tuyệt. Cuối cùng, một giải pháp không có biếnkhông có chức năng cửa sổ MySQL 8 . :)
Timo

24

Một tinh chỉnh của phiên bản của Daniel để tính phần trăm cùng với thứ hạng. Ngoài ra hai người có cùng điểm sẽ có cùng cấp bậc.

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

Kết quả của truy vấn cho một dữ liệu mẫu -

+----+-------+------+---------------+---------------+-----------------+
| 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
Mặc dù điều này không thực sự tối ưu trong hiệu suất, nhưng nó thật tuyệt vời!
Gaspa79

18

Kết hợp câu trả lời của Daniel và Salman. Tuy nhiên, thứ hạng sẽ không đưa ra khi tiếp tục trình tự với các mối quan hệ tồn tại. Thay vào đó, nó bỏ qua thứ hạng tiếp theo. Vì vậy, tối đa luôn luôn đạt số lượng hàng.

    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;

Lược đồ và trường hợp thử nghiệm:

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

Đầu ra:

+------------+------+--------+------+--------------------------+-----------------+
| 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
Tôi mới dùng MySQL nhưng giải pháp này có ổn không? Trong tài liệu MySQL nói "thứ tự đánh giá cho các biểu thức liên quan đến các biến người dùng là không xác định." dev.mysql.com/doc/refman/5.7/en/user-variables.html
narduk

13

Bắt đầu với MySQL 8, cuối cùng bạn cũng có thể sử dụng các chức năng của cửa sổ trong MySQL: https://dev.mysql.com/doc/refman/8.0/en/window-fifts.html

Truy vấn của bạn có thể được viết chính xác theo cùng một cách:

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

Nó không sai chỉ là không hoạt động với các phiên bản SQL cũ hơn. cộng với đó là một bản sao và quá khứ của câu hỏi của anh ấy nên không cảm thấy nó phù hợp với câu trả lời.
newdark-it 30/10/18

4
@ brand-it Đối với những người trên MySQL 8+, câu trả lời này rất quan trọng vì nó cho chúng tôi biết rằng Xếp hạng hiện có sẵn. Nếu tôi không cuộn xuống đến mức này, tôi sẽ cho rằng các câu trả lời trước đó là giải pháp duy nhất.
Steve Smith

1
@SteveSmith Điểm hay là thật tuyệt khi có câu trả lời này cho những người sử dụng phiên bản MYSQL mới hơn.
newdark-it

Vâng, tôi không hài lòng với rất nhiều câu trả lời với các biến người dùng và khối logic. Một phiên bản mới của MySQL cho phép thực hiện đơn giản RẤT NHIỀU với chức năng RANK () cung cấp một nhóm được phân chia theo nhóm.
James Bond

5

@Sam, quan điểm của bạn là tuyệt vời về khái niệm nhưng tôi nghĩ bạn đã hiểu sai những gì tài liệu MySQL đang nói trên trang được tham chiếu - hoặc tôi hiểu nhầm :-) - và tôi chỉ muốn thêm điều này để nếu ai đó cảm thấy không thoải mái với @ Câu trả lời của Daniel họ sẽ yên tâm hơn hoặc ít nhất là đào sâu hơn một chút.

Bạn thấy "@curRank := @curRank + 1 AS rank"bên trong SELECTkhông phải là "một tuyên bố", đó là một phần "nguyên tử" của tuyên bố nên nó an toàn.

Tài liệu bạn tham chiếu tiếp tục hiển thị các ví dụ trong đó cùng một biến do người dùng xác định trong 2 phần (nguyên tử) của câu lệnh, ví dụ , "SELECT @curRank, @curRank := @curRank + 1 AS rank".

Người ta có thể lập luận rằng @curRankđược sử dụng hai lần trong câu trả lời của @ Daniel: (1) "@curRank := @curRank + 1 AS rank"và (2) "(SELECT @curRank := 0) r"nhưng vì cách sử dụng thứ hai là một phần của FROMmệnh đề, tôi khá chắc chắn rằng nó được đảm bảo để được đánh giá trước; về cơ bản làm cho nó trở thành một tuyên bố thứ hai và trước đó.

Trên thực tế, trên cùng một trang tài liệu MySQL mà bạn đã tham chiếu, bạn sẽ thấy cùng một giải pháp trong các nhận xét - đó có thể là nơi @Daniel lấy nó từ đó; vâng, tôi biết rằng đó là những bình luận nhưng đó là những bình luận trên trang tài liệu chính thức và nó có trọng lượng.


Không ai trong số này được chứng minh bằng tài liệu. Nó chỉ là (mờ) đầu cơ. Như tất cả các câu trả lời cả sử dụng và viết cùng một biến, mà hướng dẫn sử dụng nói rõ ràng không được xác định, mặc dù hướng dẫn sử dụng có rất nhiều văn bản không hữu ích, những gì có thể hoạt động như bạn mong đợi, mà không nói những gì nó nghĩ bạn mong đợi hoặc sử dụng những gì một mô tả về hành vi không được bảo đảm là. PS Kể từ khi gán biến 8.0 bên ngoài SET không được dùng nữa.
philipxy

4

Giải pháp chuyển tiếp thẳng nhất để xác định thứ hạng của một giá trị nhất định là đếm số lượng giá trị trước nó. Giả sử chúng ta có các giá trị sau:

10 20 30 30 30 40
  • Tất cả các 30giá trị được coi là thứ 3
  • Tất cả các 40giá trị được coi là thứ 6 (thứ hạng) hoặc thứ 4 (thứ hạng dày đặc)

Bây giờ trở lại câu hỏi ban đầu. Dưới đây là một số dữ liệu mẫu được sắp xếp như mô tả trong OP (xếp hạng dự kiến ​​sẽ được thêm ở bên phải):

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

Để tính toán RANK() OVER (PARTITION BY Gender ORDER BY Age)cho Sarah , bạn có thể sử dụng truy vấn này:

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

Để tính toán RANK() OVER (PARTITION BY Gender ORDER BY Age)cho tất cả các hàng, bạn có thể sử dụng truy vấn này:

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

Và đây là kết quả (giá trị gia nhập được thêm vào bên phải):

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

Nếu bạn muốn xếp hạng chỉ một người, bạn có thể làm như sau:

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

Xếp hạng này tương ứng với chức năng RANK orory (Trường hợp nếu bạn có những người có cùng độ tuổi, họ sẽ có cùng thứ hạng và thứ hạng sau đó không liên tiếp).

Nó nhanh hơn một chút so với sử dụng một trong các giải pháp trên trong truy vấn con và chọn từ đó để có được thứ hạng của một người.

Điều này có thể được sử dụng để xếp hạng tất cả mọi người nhưng nó chậm hơn các giải pháp trên.

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

Nó có thể trở thành nhiều chậm hơn so với các giải pháp khi số lượng hàng trong trên Personbảng phát triển. Đó là O (n ^ 2) so với O (n) chậm hơn.
xmedeko

2

Để tránh " tuy nhiên " trong câu trả lời của Erandac kết hợp câu trả lời của Daniel và Salman, người ta có thể sử dụng một trong những "cách giải quyết phân vùng" sau đây

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

Xếp hạng phân vùng trong biến thể thứ 3 trong đoạn mã này sẽ trả về số thứ hạng liên tục. điều này sẽ dẫn đến một cấu trúc dữ liệu tương tự như rank() over partition bykết quả. Ví dụ, xem bên dưới. Cụ thể, phân vùngSequence sẽ luôn bắt đầu bằng 1 cho mỗi phân vùngRank mới , sử dụng phương thức này:

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');
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.