স্কোর টেবিলটিতে একটি ব্যবহারকারীর পদমর্যাদা পান


31

আমার খুব সাধারণ মাইএসকিউএল টেবিল রয়েছে যেখানে আমি হাইস্কোরগুলি সংরক্ষণ করি। দেখে মনে হচ্ছে:

Id     Name     Score

এ পর্যন্ত সব ঠিকই. প্রশ্নটি হল: ব্যবহারকারীদের র‌্যাঙ্ক কীভাবে পাব? উদাহরণস্বরূপ, আমি একটি ব্যবহারকারী আছে Nameবা Idতার র্যাঙ্ক, যেখানে সব সারি পূরণবাচক জন্য সাজানো আদেশ পেতে চান Score

একটি উদাহরণ

Id  Name    Score
1   Ida     100
2   Boo     58
3   Lala    88
4   Bash    102
5   Assem   99

এই ক্ষেত্রে, Assemএর র‌্যাঙ্ক 3 হবে, কারণ তিনি তৃতীয় সর্বোচ্চ স্কোর পেয়েছেন।

ক্যোয়ারিতে একটি সারি ফিরতে হবে, এতে প্রয়োজনীয় র্যাঙ্ক রয়েছে (কেবল)।

উত্তর:


31
SELECT id, name, score, FIND_IN_SET( score, (
SELECT GROUP_CONCAT( score
ORDER BY score DESC ) 
FROM scores )
) AS rank
FROM scores

এই তালিকা দেয়:

id name  score rank
1  Ida   100   2
2  Boo    58   5
3  Lala   88   4
4  Bash  102   1
5  Assem  99   3

একক ব্যক্তির স্কোর অর্জন:

SELECT id, name, score, FIND_IN_SET( score, (    
SELECT GROUP_CONCAT( score
ORDER BY score DESC ) 
FROM scores )
) AS rank
FROM scores
WHERE name =  'Assem'

এই ফলাফল দেয়:

id name score rank
5 Assem 99 3

স্কোরের তালিকা পাওয়ার জন্য আপনার কাছে একটি স্ক্যান থাকবে এবং অন্য স্ক্যান হবে বা এর সাথে দরকারী কিছু করার চেষ্টা করবে। scoreকলামের একটি সূচক বড় টেবিলগুলিতে কর্মক্ষমতা সহায়তা করবে।


3
পারস্পরিক সম্পর্ক (SELECT GROUP_CONCAT(score) FROM TheWholeTable)সবচেয়ে ভাল উপায় নয়। এবং এটি তৈরি করা সারিটির আকার নিয়ে সমস্যা হতে পারে।
ypercubeᵀᴹ

2
এটি সম্পর্কের ক্ষেত্রে ব্যর্থ হবে।
অরবিন্দ07

একক ব্যক্তি স্কোর ক্যোয়ারী ধীর অত্যন্ত বড় টেবিল .. অনেক ভালো জিজ্ঞাসার জন্য ক্রম (বন্ধন জন্য ফাঁক সঙ্গে) নির্ধারণ করার জন্য একটি একক ব্যক্তির স্কোর জন্য নন: SELECT 1 + COUNT(*) AS rank FROM scores WHERE score > (SELECT score FROM scores WHERE name='Assem')। যা 'কেবল' বর্তমান প্রবেশের চেয়ে উচ্চতর স্কোর সহ এন্ট্রিগুলির সংখ্যা গণনা করে। (আপনি যদি যোগ করেন তবে DISTINCTফাঁক ছাড়াই র‌্যাঙ্ক পাবেন ..)
পল

গুরুত্বপূর্ণ: GROUP_CONTAT এর একটি ডিফল্ট সীমা 1024 অক্ষর রয়েছে, বড় আকারের ডেটাতে এটি ভুল র‌্যাঙ্কের ফলস্বরূপ প্রদর্শিত হবে, উদাহরণস্বরূপ, এটি 100 র‌্যাঙ্কে থামতে পারে এবং তারপরে 0 র‌্যাঙ্ক হিসাবে রিপোর্ট করবে
প্লাস 1

30

যখন একাধিক এন্ট্রিগুলির সমান স্কোর থাকে, পরবর্তী স্থানটি পরপর হওয়া উচিত নয়। পরবর্তী র‌্যাঙ্কটি একই র‌্যাঙ্কটি ভাগ করে নেওয়ার সংখ্যা দ্বারা বৃদ্ধি করা উচিত।

এর মতো স্কোর প্রদর্শন করতে দুটি র‌্যাঙ্ক ভেরিয়েবলের প্রয়োজন

  • প্রদর্শনের জন্য র‌্যাঙ্ক ভেরিয়েবল
  • গণনা করার জন্য র‌্যাঙ্ক ভেরিয়েবল

বন্ধনগুলির সাথে র‌্যাঙ্কিংয়ের এটি আরও স্থিতিশীল সংস্করণ:

SET @rnk=0; SET @rank=0; SET @curscore=0;
SELECT score,ID,rank FROM
(
    SELECT AA.*,BB.ID,
    (@rnk:=@rnk+1) rnk,
    (@rank:=IF(@curscore=score,@rank,@rnk)) rank,
    (@curscore:=score) newscore
    FROM
    (
        SELECT * FROM
        (SELECT COUNT(1) scorecount,score
        FROM scores GROUP BY score
    ) AAA
    ORDER BY score DESC
) AA LEFT JOIN scores BB USING (score)) A;

আসুন নমুনা ডেটা দিয়ে এটি ব্যবহার করে দেখুন। প্রথমে এখানে নমুনা তথ্য রয়েছে:

use test
DROP TABLE IF EXISTS scores;
CREATE TABLE scores
(
    id int not null auto_increment,
    score int not null,
    primary key (id),
    key score (score)
);
INSERT INTO scores (score) VALUES
(50),(40),(75),(80),(55),
(40),(30),(80),(70),(45),
(40),(30),(65),(70),(45),
(55),(45),(83),(85),(60);

নমুনা ডেটা লোড করা যাক

mysql> DROP TABLE IF EXISTS scores;
Query OK, 0 rows affected (0.15 sec)

mysql> CREATE TABLE scores
    -> (
    ->     id int not null auto_increment,
    ->     score int not null,
    ->     primary key (id),
    ->     key score (score)
    -> );
Query OK, 0 rows affected (0.16 sec)

mysql> INSERT INTO scores (score) VALUES
    -> (50),(40),(75),(80),(55),
    -> (40),(30),(80),(70),(45),
    -> (40),(30),(65),(70),(45),
    -> (55),(45),(83),(85),(60);
Query OK, 20 rows affected (0.04 sec)
Records: 20  Duplicates: 0  Warnings: 0

এর পরে, ব্যবহারকারী ভেরিয়েবলগুলি আরম্ভ করুন:

mysql> SET @rnk=0; SET @rank=0; SET @curscore=0;
Query OK, 0 rows affected (0.01 sec)

Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

এখন, কোয়েরির আউটপুট এখানে:

mysql> SELECT score,ID,rank FROM
    -> (
    ->     SELECT AA.*,BB.ID,
    ->     (@rnk:=@rnk+1) rnk,
    ->     (@rank:=IF(@curscore=score,@rank,@rnk)) rank,
    ->     (@curscore:=score) newscore
    ->     FROM
    ->     (
    ->         SELECT * FROM
    ->         (SELECT COUNT(1) scorecount,score
    ->         FROM scores GROUP BY score
    ->     ) AAA
    ->     ORDER BY score DESC
    -> ) AA LEFT JOIN scores BB USING (score)) A;
+-------+------+------+
| score | ID   | rank |
+-------+------+------+
|    85 |   19 |    1 |
|    83 |   18 |    2 |
|    80 |    4 |    3 |
|    80 |    8 |    3 |
|    75 |    3 |    5 |
|    70 |    9 |    6 |
|    70 |   14 |    6 |
|    65 |   13 |    8 |
|    60 |   20 |    9 |
|    55 |    5 |   10 |
|    55 |   16 |   10 |
|    50 |    1 |   12 |
|    45 |   10 |   13 |
|    45 |   15 |   13 |
|    45 |   17 |   13 |
|    40 |    2 |   16 |
|    40 |    6 |   16 |
|    40 |   11 |   16 |
|    30 |    7 |   19 |
|    30 |   12 |   19 |
+-------+------+------+
20 rows in set (0.18 sec)

দয়া করে নোট করুন যে একই স্কোর ভাগ করে নেওয়ার একাধিক আইডি কীভাবে একই পদমর্যাদায় রয়েছে। এছাড়াও লক্ষ করুন যে র‌্যাঙ্কটি একটানা নয়।

একবার চেষ্টা করে দেখো !!!


যেহেতু এটি সেশন-স্কোপড ভেরিয়েবলগুলি ব্যবহার করছে, এটি কি নিরাপদ যদি বলা হয়, একাধিক প্রান্ত-ব্যবহারকারী একই সাথে স্কোরবোর্ডের জন্য অনুরোধ করছেন? অন্য ব্যবহারকারীও এই কোয়েরিটি চালাচ্ছেন বলে ফলাফলের আলাদা ফলাফল রাখা কি সম্ভব? অনেক ক্লায়েন্ট একবারে হিট করে এই ক্যোয়ারির সামনে একটি এপিআই কল্পনা করুন।
Xaero Degreaz

@ কেয়েরো ডেগ্রিয়াজ আপনি ঠিক বলেছেন, এটা সম্ভব। কোনও গেমের জন্য গণনা করার স্থানগুলি কল্পনা করুন। একজন ব্যক্তি উচ্চ স্কোরকে পরাজিত করে বা শীর্ষ এক্স স্কোরগুলিতে প্রবেশ করার পরে একজন ব্যবহারকারী র‌্যাঙ্কের জন্য অনুসন্ধান করে এবং অন্য ব্যবহারকারী 5 সেকেন্ড অনুসন্ধান করে। তবুও, সার্ভার স্তরের চেয়ে অ্যাপ্লিকেশন পর্যায়ে যদি র‌্যাঙ্কিং করা হয়ে থাকে তবে একই ঘটনা ঘটতে পারে।
রোল্যান্ডোমাইএসকিউএলডিবিএ

জবাবের জন্য ধন্যবাদ. সময়ের সাথে সাথে ডেটাগুলি অস্থায়ীভাবে স্থানান্তরিত হয় বা না আমার উদ্বেগটি আসলেই নয়, আমার উদ্বেগটি হ'ল কোয়েরিটি সম্পাদনকারী একাধিক ব্যবহারকারী সেশন-স্কোপড ভেরিয়েবলগুলিতে সঞ্চিত ডেটাটি সংশোধন / ওভাররাইটিং করবেন অন্য ব্যবহারকারীরাও কোয়েরিটি সম্পাদন করছেন। যে জানার জন্য?
Xaero Degreaz

@ কেয়েরো ডেগ্রিয়াজ এটি সেশন স্কোপ ভেরিয়েবলের সৌন্দর্য। তারা কেবল আপনার অধিবেশনে এবং অন্য কারও নয়। আপনি অন্য ব্যবহারকারীদের থেকে সেশন ভেরিয়েবলগুলি দেখতে পাবেন না এবং কেউ আপনার সেশন ভেরিয়েবলগুলি দেখতে পাবে না।
রোল্যান্ডোমাইএসকিউএলডিবিএ

ঠিক আছে, এটাই আমি বিশ্বাসের দিকে ঝুঁকে ছিলাম - এই সেশনের ভেরিয়েবলগুলি সংযোগের দিকে যায় এবং একক সময়ে একক সংযোগ একাধিক ব্যক্তি দখল করতে পারে না। সংযোগটি একবার নিখরচায় ফেলার পরে, বা পুনরায় পুলে ফেলে দেওয়া হলে, অন্য কোনও ব্যবহারকারী সংযোগটি নিয়ে যেতে পারেন এবং সেশন ভেরিয়েবলগুলি পুনরায় আরম্ভ করা হবে (এই কোয়েরিটি সম্পাদন করার সময়)। তথ্যের জন্য আবারও ধন্যবাদ।
Xaero Degreaz

13
SELECT 
    id, 
    Name,
    1+(SELECT count(*) from table_name a WHERE a.Score > b.Score) as RNK,
    Score
FROM table_name b;

9

একটি বিকল্প হ'ল ব্যবহারকারীর ভেরিয়েবলগুলি ব্যবহার করা হবে:

SET @i=0;
SELECT id, name, score, @i:=@i+1 AS rank 
 FROM ranking 
 ORDER BY score DESC;

4

গৃহীত উত্তর একটি সম্ভাব্য সমস্যা আছে। যদি দুটি বা ততোধিক অভিন্ন স্কোর থাকে তবে র‌্যাঙ্কিংয়ে ফাঁক থাকবে। এই পরিবর্তিত উদাহরণে:

 id name  score rank
 1  Ida   100   2
 2  Boo    58   5
 3  Lala   99   3
 4  Bash  102   1
 5  Assem  99   3

৫৮ এর স্কোরের র‌্যাঙ্ক ৫ রয়েছে এবং র‌্যাঙ্ক ৪ নেই।

আপনি করতে চান ব্যাপারে নিশ্চিত হওয়ার স্থান কোন ফাঁক, ব্যবহার হয় DISTINCTGROUP_CONCATস্বতন্ত্র স্কোর একটি তালিকা তৈরী করতে:

SELECT id, name, score, FIND_IN_SET( score, (
SELECT GROUP_CONCAT( DISTINCT score
ORDER BY score DESC ) FROM scores)
) AS rank
FROM scores

ফলাফল:

id name  score rank
1  Ida   100   2
2  Boo    58   4
3  Lala   99   3   
4  Bash  102   1
5  Assem  99   3

এটি একটি একক ব্যবহারকারীর র‌্যাঙ্ক পাওয়ার জন্যও কাজ করে:

SELECT id, name, score, FIND_IN_SET( score, (    
SELECT GROUP_CONCAT(DISTINCT score
ORDER BY score DESC ) 
FROM scores )
) AS rank
FROM scores
WHERE name =  'Boo'

ফলাফল:

id name score rank
 2  Boo   58    4

একক ব্যবহারকারীর র‌্যাঙ্ক ক্যোয়ারী ব্যবহার করে COUNTএবং পরিবর্তে একটি subquery ব্যবহার করে প্রচুরভাবে অনুকূলিত করা যেতে পারে । স্বীকৃত উত্তরে আমার মন্তব্য দেখুন
পল

ভাল নোট এবং বর্ধন। খুব ভাল কাজ করে
এসএমমোসাভি

3

এখানে সেরা উত্তর:

SELECT 1 + (SELECT count( * ) FROM highscores a WHERE a.score > b.score ) AS rank FROM
highscores b WHERE Name = 'Assem' ORDER BY rank LIMIT 1 ;

এই প্রশ্নটি ফিরে আসবে:

3


এটা ভেবে আমার একটা ছোট সমস্যা হচ্ছে। উদাহরণস্বরূপ: যদি প্রথম দুটি ব্যবহারকারীর স্কোর আলাদা থাকে এবং বাকী সকলের 0 থাকে তবে শূন্য-স্কোর লোকের জন্য র‌্যাঙ্কিং # 3 এর পরিবর্তে # 4 হয়। তবে প্রথমটি সঠিকভাবে পেয়েছে # 1 এবং দ্বিতীয়টি # 2। কোন ধারনা?
fersarr

3

এই সমাধানটি সম্পর্কের ক্ষেত্রে দেয় DENSE_RANK:

SELECT *,
IF (@score=s.Score, @rank:=@rank, @rank:=@rank+1) rank,
@score:=s.Score score
FROM scores s,
(SELECT @score:=0, @rank:=0) r
ORDER BY points DESC

0

নিম্নলিখিত কাজটি (আপনার টেবিলকে স্কোর বলে ধরে নেওয়া হয় না)?

SELECT COUNT(id) AS rank FROM Scores 
WHERE score <= (SELECT score FROM Scores WHERE Name = "Assem")

-4

আমার কাছে এটি রয়েছে যা ভেরিয়েবলগুলির সাথে একই ফলাফল দেয়। এটি বন্ধনগুলির সাথে কাজ করে এবং এটি আরও দ্রুত হতে পারে:

SELECT COUNT(*)+1 as rank
FROM 
(SELECT score FROM scores ORDER BY score) AS sc
WHERE score <
(SELECT score FROM scores WHERE Name="Assem")

আমি এটি পরীক্ষা করিনি, তবে আমি এমন একটি ব্যবহার করছি যা পুরোপুরি কার্যকর হয়, যা আমি এখানে আপনি যে ভেরিয়েবলগুলি ব্যবহার করেছিলাম তার সাথে এটি মানিয়ে নিয়েছিলাম।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.