MySQL - चयन पर पंक्ति संख्या प्राप्त करें


181

यदि आइटम सॉर्ट किए जाते हैं तो क्या मैं एक चयन स्टेटमेंट चला सकता हूं और पंक्ति संख्या प्राप्त कर सकता हूं?

मेरे पास इस तरह की एक तालिका है:

mysql> describe orders;
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| orderID     | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| itemID      | bigint(20) unsigned | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

मैं तब आईडी द्वारा आदेशों की संख्या प्राप्त करने के लिए इस क्वेरी को चला सकता हूं:

SELECT itemID, COUNT(*) as ordercount
FROM orders
GROUP BY itemID ORDER BY ordercount DESC;

यह मुझे itemIDइस तरह तालिका में प्रत्येक की एक गिनती देता है :

+--------+------------+
| itemID | ordercount |
+--------+------------+
|    388 |          3 |
|    234 |          2 |
|   3432 |          1 |
|    693 |          1 |
|   3459 |          1 |
+--------+------------+

मैं पंक्ति संख्या भी प्राप्त करना चाहता हूं, इसलिए मैं बता सकता हूं कि itemID=388पहली पंक्ति है, 234दूसरी है, आदि (अनिवार्य रूप से आदेशों की रैंकिंग, केवल एक कच्ची गिनती नहीं है)। मुझे पता है कि मैं जावा में ऐसा कर सकता हूं जब मुझे परिणाम सेट वापस मिल जाएगा, लेकिन मैं सोच रहा था कि क्या SQL में इसे पूरी तरह से संभालने का कोई तरीका था।

अपडेट करें

रैंक सेट करना इसे परिणाम सेट में जोड़ता है, लेकिन ठीक से आदेश नहीं दिया गया है:

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

mysql> SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
    -> FROM orders
    -> GROUP BY itemID ORDER BY rank DESC;
+------+--------+------------+
| rank | itemID | ordercount |
+------+--------+------------+
|    5 |   3459 |          1 |
|    4 |    234 |          2 |
|    3 |    693 |          1 |
|    2 |   3432 |          1 |
|    1 |    388 |          3 |
+------+--------+------------+
5 rows in set (0.00 sec)

1
भविष्य के संदर्भ के लिए: यदि आप रैंक 1 से रैंक 5 तक ऑर्डर करना चाहते हैं, तो ORDER BY rank ASC(ASCending क्रम में रैंक द्वारा आदेश) का उपयोग करें। मुझे लगता है कि आप क्या मतलब है, लेकिन ठीक से नहीं आदेश दिया
BlueCacti

जवाबों:


179

इस पर एक नजर ।

अपनी क्वेरी को इसमें बदलें:

SET @rank=0;
SELECT @rank:=@rank+1 AS rank, itemID, COUNT(*) as ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC;
SELECT @rank;

अंतिम चयन आपकी गिनती है।


1
यह परिणाम सेट में रैंक जोड़ता है, लेकिन उन्हें उचित क्रम में नहीं डालता है - परिणामों के साथ अद्यतन प्रश्न
जॉर्ज

1
रखने की कोशिश करें ORDER BY ordercount DESC, और फिर पूरी क्वेरी को दूसरे में लपेटें SELECTजो पहले एक से सब कुछ प्राप्त करता है, लेकिन रैंक कॉलम (इस मामले में 0) द्वारा आदेश।
माइक सियालॉविक

1
क्या आप इसका एक उदाहरण दिखा सकते हैं? मैं चयन कैसे लपेटूंगा?
जॉर्ज

9
स्वैमीबॉप के उत्तर की जाँच करें
thaddeusmt

1
@ माइकलाइकोविज़, यह काम नहीं करता है । सही उत्तर के लिए मेरे समाधान या स्वामीबबॉप के समाधान का संदर्भ लें।
पचेरियर

178
SELECT @rn:=@rn+1 AS rank, itemID, ordercount
FROM (
  SELECT itemID, COUNT(*) AS ordercount
  FROM orders
  GROUP BY itemID
  ORDER BY ordercount DESC
) t1, (SELECT @rn:=0) t2;

1
स्पष्ट करने के लिए धन्यवाद, इससे मुझे होने वाली समस्या का समाधान हो गया।
thaddeusmt

1
धन्यवाद, यह वास्तव में मेरे लिए उपयोगी था :) मुझे आश्चर्य है कि परिणाम सेट से पंक्ति 'अनुक्रमित' प्राप्त करने का अधिक सरल तरीका नहीं है ... लेकिन वैसे भी धन्यवाद यह आसान था।
चूहा

आप SELECT \ @rn: = \ @ rn + 1 AS रैंक, itemID, ordercount, \ @tot: = \ @ कुल + के रूप में \ _ कुल + के रूप में पहला चयन विवरण बदलकर एक वृद्धिशील कुल के साथ एक चौथी पंक्ति जोड़ सकते हैं। \ @Tot के प्रारंभिक मान को परिभाषित करने के लिए इसे t2 के बाद जोड़ा जाना चाहिए: (SELECT \ @tot: = 0) t3। \ _ को हर \ _ से पहले हटाएं, जिसे मुझे मिनी-मार्कडाउन स्वरूपण को दरकिनार करने के लिए उपयोग करना था।
Jan Ehrhardt

2
किसी की प्रासंगिकता व्याख्या कर सकते हैं t1और t2?
जारेड

2
@Jared, MySQL सिंटैक्स के लिए बस कुछ होना चाहिए। यह कुछ भी हो सकता है, xऔर भी y
पचेरियर

31

स्वामीबॉप का समाधान काम करता है, लेकिन table.*सिंटैक्स का लाभ उठाकर , हम आंतरिक के कॉलम नामों को दोहराने से बच सकते हैं selectऔर एक सरल / छोटा परिणाम प्राप्त कर सकते हैं:

SELECT @r := @r+1 , 
       z.* 
FROM(/* your original select statement goes in here */)z, 
(SELECT @r:=0)y;

ताकि आप दे देंगे:

SELECT @r := @r+1 , 
       z.* 
FROM(
     SELECT itemID, 
     count(*) AS ordercount
     FROM orders
     GROUP BY itemID
     ORDER BY ordercount DESC
    )z,
    (SELECT @r:=0)y;

क्या आप संयोग से जानते हैं कि @r := @r + 1एक चुनिंदा कथन का उपयोग करना क्यों काम करता है, लेकिन अगर यह एक संग्रहीत प्रक्रिया में है declare r int; set r = 0;, तो यह शिकायत करता है (ऑन r := r +1)?
डेन एम।

@ स्पेसर, पंक्तियों का क्रम भी है जो कि कहीं दूसरे गारंटीड की गारंटी है? मुझे पता है कि खंड द्वारा क्रम के बिना चयन द्वारा लौटाए गए पंक्तियों के आदेश की कहीं भी गारंटी नहीं है, और सबसे बाहरी चयन बिल्कुल यही है, हालांकि यह आंतरिक आदेशित चयन से चयन करता है, इसलिए यह एक अपवाद हो सकता है। यदि यह नहीं है, हालांकि, मैं यह नहीं देख सकता कि यह एक सही समाधान कैसे है क्योंकि इसमें चिबू के माइक के समान दोष होगा - कोई गारंटी नहीं है कि किस क्रम में चयन रिकॉर्ड के माध्यम से जाएगा और उन्हें नंबर देगा।
डेन एम।

क्या आपको पता होगा कि जब भी क्षेत्र सूची में नहीं होता है तो ORDER BY काम क्यों नहीं कर रहा है? मेरा परिणाम देखें: hastebin.com/aluqefunoy.rb
शीतकालीन

11

आप इसे करने के लिए MySQL चर का उपयोग कर सकते हैं। इस तरह से कुछ काम करना चाहिए (हालांकि, इसमें दो प्रश्न शामिल हैं)।

SELECT 0 INTO @x;

SELECT itemID, 
       COUNT(*) AS ordercount, 
       (@x:=@x+1) AS rownumber 
FROM orders 
GROUP BY itemID 
ORDER BY ordercount DESC; 

2
सावधान, यह काम नहीं करेगा क्योंकि चर का मूल्यांकन order byहोने के बाद होता है @x। अन्य स्तंभों का उपयोग करके आदेश देकर प्रयोग करने का प्रयास करें। इसके अलावा descऔर दोनों के साथ प्रयोग करें asc। आप देखेंगे कि कई बार वे विफल हो जाएंगे और केवल एक बार जब यह काम करता है, तो यह आपके मूल "चयन" के आदेश के कारण उसी क्रम के कारण शुद्ध भाग्य से होता है order by। मेरा समाधान और / या स्वामीबॉप का समाधान देखें।
पचेरियर

@Pacerier क्या आप इसके बारे में निश्चित हैं? मैंने एक अलग उदाहरण में समान क्वेरी को थका दिया है (मूल रूप से संख्याओं के कॉलम से चयन करें, और उनके क्रम के अनुसार उन्हें संख्या दें) ऐसा लगता था कि यदि मैंने var / row num से आदेश दिया, जब उसने परिणामी पंक्तियों के क्रम को बदल दिया, लेकिन प्रत्येक संख्या में एक ही पंक्ति संख्या थी। लेकिन अगर मैं संख्या कॉलम द्वारा आदेश देता हूं, तो ASC/ DESCउस क्रम को बदल देगा जिसमें उन संख्याओं को क्रमांकित किया गया था (सबसे छोटी से सबसे बड़ी या इसके विपरीत)। इसलिए ऐसा लगता है कि order byपहले इस मामले का मूल्यांकन किया गया था।
डेन एम।

1

यह अब MySQL 8.0 और MariaDB 10.2 में बनाया गया है:

SELECT
  itemID, COUNT(*) as ordercount,
  ROW_NUMBER OVER (PARTITION BY itemID ORDER BY rank DESC) as rank
FROM orders
GROUP BY itemID ORDER BY rank DESC
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.