MySQL में रैंक फ़ंक्शन


155

मुझे ग्राहकों की रैंक का पता लगाने की आवश्यकता है। यहाँ मैं अपनी आवश्यकता के लिए संबंधित ANSI मानक SQL क्वेरी जोड़ रहा हूँ। कृपया इसे MySQL में बदलने में मेरी मदद करें।

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

क्या MySQL में रैंक का पता लगाने के लिए कोई फ़ंक्शन है?

जवाबों:


266

एक विकल्प रैंकिंग रैंकिंग चर का उपयोग करना है, जैसे कि निम्नलिखित:

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)

52
+1 कुटिल इनलाइन आरंभीकरण के लिए, यह एक सुंदर चाल है।
चार्ल्स

28
क्या उसने विभाजन नहीं मांगा? विभाजन की मेरी समझ यह है कि परिणाम सेट में पुरुष और महिला के लिए अलग-अलग रैंकिंग होगी।
जेसी ढिल्लों

2
@ जेसे: अगर ऐसा है, तो मैंने हाल ही में एक ऐसे ही सवाल का जवाब दिया: stackoverflow.com/questions/3162389/multiple-ranks-in-one-table
डैनियल वेसलो

6
क्या होगा अगर मैं एनी और बॉब दोनों को 4 रैंक देना चाहता हूं?
फहीम पारकर

8
यह प्रश्न से उदाहरण को लागू नहीं करता है क्योंकि यह partition by genderविश्लेषणात्मक फ़ंक्शन के भाग को याद करता है (जो "संख्या" प्रति लिंग रैंक रैंक समग्र परिणाम के लिए नहीं है)
a_horse_with_no_name

53

यहाँ एक सामान्य समाधान है जो विभाजन से लेकर पंक्तियों तक में सघन पद प्रदान करता है। यह उपयोगकर्ता चर का उपयोग करता है:

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;

ध्यान दें कि चर असाइनमेंट को CASEअभिव्यक्ति के अंदर रखा गया है । यह (सिद्धांत में) मूल्यांकन मुद्दे के आदेश का ख्याल रखता है। IS NOT NULLडेटाप्रकार रूपांतरण और लघु सर्किटिंग मुद्दों को संभालने के लिए जोड़ा गया है।

पुनश्च: इसे आसानी से टाई के लिए जाँच करने वाली सभी शर्तों को हटाकर विभाजन पर पंक्ति संख्या में परिवर्तित किया जा सकता है।

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

Db <> फिडल पर डेमो


2
यह समाधान, या मुकेश का समाधान, सही समाधान होना चाहिए। हालांकि तकनीकी रूप से मेरा मानना ​​है कि आप दोनों लोगों के समाधान घने रैंकिंग का प्रतिनिधित्व करते हैं न कि नियमित रैंक का। यहाँ मतभेदों की एक अच्छी व्याख्या है: sqlservercurry.com/2009/04/…
modulitos

क्या आप हमें यह भी बता सकते हैं कि .php कोड वास्तव में कैसा होना चाहिए? मैंने पालन करने की कोशिश की, लेकिन ऊपर कोड काम नहीं करता है। .Php प्रारूप में इनपुट कैसे करें?
रचनाकार

यह समाधान बहुत सामान्य नहीं है; यदि रैंक_ कोल्युमेंट का मान 0. sqlfiddle.com/#/2/9c5dd/1 है
माइक

1
@ माइक कैस स्टेटमेंट में ईएलएसई सेक्शन जोड़ें:ELSE @rank_count := @rank_count + 1
प्रिंस ओडेम

1
@ आभाष ORDER BY gender, age DESC?
सलमान ए

52

जबकि सबसे उत्कीर्ण उत्तर रैंक, यह विभाजन नहीं करता है, आप एक स्वयं कर सकते हैं पूरी चीज़ को भी विभाजित करने के लिए सम्मिलित हों:

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

उदाहरण

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

उत्तर :

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

यह सटीक उत्तर है क्योंकि मुझे विभाजन रैंकिंग करने की आवश्यकता है। धन्यवाद महोदय!
किम स्टैक

IMO में @Sam किडमैन के उत्तर: O (n ^ 2) के रूप में एक ही जटिलता है। लेकिन पता नहीं है कि क्या MySQL में इसे बेहतर करना संभव है।
xmedeko

की जाँच करें onlamp.com/pub/a/mysql/2007/03/29/... उसी तर्ज पर एक महान ट्यूटोरियल के लिए
ferics2

रैंक प्राप्त करने के लिए स्व-जुड़ें! एक दम बढ़िया। अंत में, चर के बिना और MySQL 8 विंडो फ़ंक्शन के बिना एक समाधान । :)
टिमो

24

रैंक के साथ प्रतिशतक की गणना करने के लिए डैनियल के संस्करण का एक मोड़। साथ ही समान अंक वाले दो लोगों को समान रैंक मिलेगी।

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

नमूना डेटा के लिए क्वेरी के परिणाम -

+----+-------+------+---------------+---------------+-----------------+
| 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
हालांकि यह प्रदर्शन में वास्तव में इष्टतम नहीं है, यह बहुत बढ़िया है!
गैसपा 79३

18

डैनियल और सलमान के जवाब का संयोजन। हालांकि, रैंक नहीं देगा क्योंकि संबंधों के साथ अनुक्रम जारी है। इसके बजाय यह रैंक को अगले पर छोड़ देता है। इसलिए अधिकतम हमेशा पंक्ति गणना तक पहुंचें।

    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;

स्कीम और टेस्ट केस:

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

आउटपुट:

+------------+------+--------+------+--------------------------+-----------------+
| 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
मैं MySQL के लिए नया हूं लेकिन क्या यह समाधान ठीक है? MySQL डॉक्स में कहा गया है "उपयोगकर्ता चर को शामिल करने वाले भावों के मूल्यांकन का क्रम अपरिभाषित है।" dev.mysql.com/doc/refman/5.7/en/user-variables.html
narduk

13

MySQL 8 से शुरू होकर, आप अंततः MySQL में भी विंडो फ़ंक्शंस का उपयोग कर सकते हैं: https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

आपकी क्वेरी ठीक उसी तरह लिखी जा सकती है:

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

यह गलत नहीं है सिर्फ SQL के पुराने संस्करणों के साथ काम नहीं करता है। इसके अलावा यह कॉपी और उसके सवाल के अतीत की तरह था, इसलिए ऐसा नहीं लगता कि यह जवाब में फिट बैठता है।
newdark-it

4
@ ब्रांड-यह MySQL 8+ वालों के लिए, यह उत्तर महत्वपूर्ण है क्योंकि यह बताता है कि रैंक अब उपलब्ध है। अगर मैंने इसे दूर तक स्क्रॉल नहीं किया था, तो मुझे लगता है कि पहले वाले उत्तर एकमात्र समाधान थे।
स्टीव स्मिथ

1
@SteveSmith अच्छी बात यह है कि उन लोगों के लिए यह जवाब अच्छा है जो MYSQL के नए संस्करण का उपयोग करते हैं।
newdark-it 14

हां, मैं उपयोगकर्ता चर और तर्क ब्लॉक के साथ बहुत सारे उत्तरों से हतोत्साहित हूं। MySQL का एक नया संस्करण इसे RANK () फ़ंक्शन के साथ सरल बनाता है जो विभाजन द्वारा निर्मित में प्रदान करता है।
जेम्स बॉन्ड

5

@Sam, आपकी बात अवधारणा में उत्कृष्ट है, लेकिन मुझे लगता है कि आपको गलत समझा गया कि MySQL डॉक्स संदर्भित पृष्ठ पर क्या कह रहे हैं - या मुझे गलत समझे :-) - और मैं सिर्फ इसे जोड़ना चाहता था ताकि अगर कोई @ के साथ असहज महसूस करे तो डैनियल का जवाब है कि वे अधिक आश्वस्त होंगे या कम से कम थोड़ी गहरी खुदाई करेंगे।

आप "@curRank := @curRank + 1 AS rank"अंदर देखते हैं कि SELECTयह "एक कथन" नहीं है, यह कथन का एक "परमाणु" भाग है, इसलिए यह सुरक्षित होना चाहिए।

आपके द्वारा संदर्भित दस्तावेज़ उदाहरणों को दिखाने के लिए जाता है जहां कथन के 2 (परमाणु) भागों में समान उपयोगकर्ता-परिभाषित चर, उदाहरण के लिए "SELECT @curRank, @curRank := @curRank + 1 AS rank",।

कोई यह तर्क दे सकता है कि @curRank@ डैनियल के उत्तर में दो बार उपयोग किया जाता है: (1) -और "@curRank := @curRank + 1 AS rank"(2) "(SELECT @curRank := 0) r"लेकिन चूंकि दूसरा उपयोग FROMक्लॉज का हिस्सा है , मुझे पूरा यकीन है कि इसका पहले मूल्यांकन किए जाने की गारंटी है; अनिवार्य रूप से यह एक दूसरा, और पूर्ववर्ती, बयान कर रहा है।

वास्तव में, उसी MySQL डॉक्स पृष्ठ पर जिसे आपने संदर्भित किया था, आपको टिप्पणियों में एक ही समाधान दिखाई देगा - यह हो सकता है कि @Daniel इसे कहां से मिला; हाँ, मुझे पता है कि यह टिप्पणियां हैं लेकिन यह आधिकारिक डॉक्स पृष्ठ पर टिप्पणियां हैं और इससे कुछ वजन होता है।


इसमें से कोई भी दस्तावेज द्वारा उचित नहीं है। यह सिर्फ (फजी) अटकलें हैं। जैसा कि सभी उत्तर एक ही चर का उपयोग करते हुए और लिखते हुए दोनों हैं, जो मैनुअल कहता है कि स्पष्ट रूप से परिभाषित नहीं किया गया है, हालांकि मैनुअल में बहुत अधिक अप्राप्य पाठ है जो आप अपेक्षा के अनुसार काम कर सकते हैं, बिना यह कहे कि आप क्या सोचते हैं या क्या उपयोग करते हैं गैर-गारंटीकृत व्यवहार का विवरण है। PS SET के बाहर 8.0 चर असाइनमेंट के रूप में पदावनत किया गया है।
फिलीपिक्सी

4

किसी दिए गए मान के रैंक को निर्धारित करने के लिए सबसे सीधा आगे का समाधान इससे पहले मूल्यों की संख्या की गणना करना है। मान लें कि हमारे पास निम्नलिखित मूल्य हैं:

10 20 30 30 30 40
  • सभी 30मान 3 माने जाते हैं
  • सभी 40मान 6 वें (रैंक) या 4 वें (घने रैंक) माने जाते हैं

अब मूल प्रश्न पर वापस आते हैं। यहां कुछ नमूना डेटा दिए गए हैं, जिन्हें ओपी में वर्णित के अनुसार क्रमबद्ध किया गया है (अपेक्षित रैंक दाईं ओर जोड़े गए हैं):

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

सारा के लिए गणना करने के RANK() OVER (PARTITION BY Gender ORDER BY Age)लिए , आप इस क्वेरी का उपयोग कर सकते हैं:

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

सभी पंक्तियों की गणना के RANK() OVER (PARTITION BY Gender ORDER BY Age)लिए आप इस क्वेरी का उपयोग कर सकते हैं:

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

और यहाँ परिणाम है (शामिल मूल्य सही पर जोड़े जाते हैं):

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

यदि आप केवल एक व्यक्ति को रैंक करना चाहते हैं, तो आप निम्न कार्य कर सकते हैं:

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

यह रैंकिंग ओरेकल आरएएनसी फ़ंक्शन से मेल खाती है (यदि आपके पास समान आयु वाले लोग हैं तो उन्हें समान रैंक मिलती है, और उसके बाद की रैंकिंग गैर-निरंतर है)।

उपर्युक्त समाधानों में से किसी एक का उपयोग करने और किसी एक व्यक्ति की रैंकिंग प्राप्त करने के लिए चयन करने की तुलना में यह थोड़ा तेज़ है।

यह सभी को रैंक करने के लिए इस्तेमाल किया जा सकता है लेकिन यह उपरोक्त समाधानों की तुलना में धीमा है।

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

तालिका में पंक्तियों की संख्या बढ़ने पर यह उपरोक्त समाधानों की तुलना में बहुत धीमा हो सकता Personहै। यह O (n ^ 2) बनाम O (n) धीमा है।
xmedeko

2

डैनियल और सलमान के जवाब के संयोजन में एरंडैक के उत्तर में " हालांकि " से बचने के लिए , कोई भी निम्नलिखित "विभाजन वर्कअराउंड" में से एक का उपयोग कर सकता है।

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

इस कोड स्निपेट में तीसरे संस्करण में विभाजन रैंकिंग निरंतर रैंकिंग संख्या लौटाएगी। यह rank() over partition byपरिणाम के समान डेटा संरचना को जन्म देगा । एक उदाहरण के रूप में, नीचे देखें। विशेष रूप से, इस पद्धति का उपयोग करते हुए, विभाजन प्रत्येक नए विभाजन के लिए हमेशा 1 से शुरू होगा :

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');
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.